Skip to content

Commit

Permalink
DockerCon 2023 πŸ³βœ…πŸŽ‰πŸ³βœ…πŸŽ‰
Browse files Browse the repository at this point in the history
  • Loading branch information
BretFisher authored Oct 4, 2023
1 parent d88b115 commit bf6de8d
Show file tree
Hide file tree
Showing 14 changed files with 222 additions and 214 deletions.
91 changes: 53 additions & 38 deletions README.md

Large diffs are not rendered by default.

18 changes: 14 additions & 4 deletions docker-compose.yml β†’ compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,31 @@
services:
node:
build:
dockerfile: dockerfiles/5.Dockerfile
dockerfile: dockerfiles/3.Dockerfile
context: .
# build to the stage named dev
target: dev
volumes:
- .:/app
# Not needed when `develop: watch` is used
# volumes:
# - .:/app
ports:
# use docker compose ps to see which host port is used
- "3000"
depends_on:
db:
condition: service_healthy
develop:
watch:
- action: sync
path: ./
target: /app
- action: rebuild
path: package.json
- action: rebuild
path: package-lock.json

db:
image: postgres
image: postgres:alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
Expand Down
21 changes: 10 additions & 11 deletions dockerfiles/1.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
# syntax=docker/dockerfile:1

###
## Example: run as non-root user
## Example: The most basic, CORRECT, Dockerfile for Node.js
###

# alwyas use slim and the lastest debian distro offered
FROM node:16-bullseye-slim
FROM node:20-bookworm-slim@sha256:8d26608b65edb3b0a0e1958a0a5a45209524c4df54bbe21a4ca53548bc97a3a5

EXPOSE 3000

# change permissions to non-root user
RUN mkdir /app && chown -R node:node /app
# add user first, then set WORKDIR to set permissions
USER node

WORKDIR /app

USER node

# copy in with correct permissions. Using * prevents errors if file is missing
COPY --chown=node:node package*.json yarn*.lock ./
COPY --chown=node:node package*.json ./

# use ci to only install packages from lock files
# we don't have a dev image/stage yet (in future example)
RUN npm ci --only=production && npm cache clean --force
RUN npm ci --omit=dev && npm cache clean --force

# copy files with correct permissions
COPY --chown=node:node . .

# we haven't fixed CMD yet (in future example)
CMD ["npm", "start"]
# change command to run node directly
CMD ["node", "./bin/www"]
24 changes: 12 additions & 12 deletions dockerfiles/2.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
FROM node:16-bullseye-slim
# syntax=docker/dockerfile:1

###
## Example: run tini first, as PID 1
###

FROM node:20-bookworm-slim@sha256:8d26608b65edb3b0a0e1958a0a5a45209524c4df54bbe21a4ca53548bc97a3a5

# replace npm in CMD with tini for better kernel signal handling
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
tini \
&& rm -rf /var/lib/apt/lists/*
ENV NODE_ENV=production
ENV TINI_VERSION=v0.19.0
ADD --chmod=755 https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /usr/local/bin/tini

# set entrypoint to always run commands with tini
ENTRYPOINT ["/usr/bin/tini", "--"]
ENTRYPOINT ["/usr/local/bin/tini", "--"]

EXPOSE 3000

RUN mkdir /app && chown -R node:node /app
USER node

WORKDIR /app

USER node

COPY --chown=node:node package*.json yarn*.lock ./
COPY --chown=node:node package*.json ./

RUN npm ci --only=production && npm cache clean --force
RUN npm ci --omit=dev && npm cache clean --force

COPY --chown=node:node . .

# change command to run node directly
CMD ["node", "./bin/www"]
28 changes: 14 additions & 14 deletions dockerfiles/3.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
# syntax=docker/dockerfile:1

###
## Adding stages for dev and prod
###
FROM node:16-bullseye-slim as base

FROM node:20-bookworm-slim@sha256:8d26608b65edb3b0a0e1958a0a5a45209524c4df54bbe21a4ca53548bc97a3a5 as base
ENV NODE_ENV=production
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
tini \
&& rm -rf /var/lib/apt/lists/*
ENV TINI_VERSION=v0.19.0
ADD --chmod=755 https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /usr/local/bin/tini
EXPOSE 3000
RUN mkdir /app && chown -R node:node /app
WORKDIR /app
USER node
COPY --chown=node:node package*.json yarn*.lock ./
RUN npm ci --only=production && npm cache clean --force
COPY --chown=node:node . .
CMD ["node", "./bin/www"]
WORKDIR /app
COPY --chown=node:node package*.json ./
RUN npm ci --omit=dev && npm cache clean --force
ENV PATH=/app/node_modules/.bin:$PATH

# dev stage
FROM base as dev
ENV NODE_ENV=development
ENV PATH=/app/node_modules/.bin:$PATH
RUN npm install
COPY --chown=node:node . .
CMD ["nodemon", "./bin/www", "--inspect=0.0.0.0:9229"]

# prod stage
FROM base as prod
ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["node", "./bin/www"]
COPY --chown=node:node . .
ENTRYPOINT ["/usr/local/bin/tini", "--"]
CMD ["node", "./bin/www"]
43 changes: 0 additions & 43 deletions dockerfiles/4.Dockerfile

This file was deleted.

60 changes: 0 additions & 60 deletions dockerfiles/5.Dockerfile

This file was deleted.

15 changes: 5 additions & 10 deletions dockerfiles/distroless.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# syntax=docker/dockerfile:1

###
## Distroless in Prod. Multi-stage dev/test/prod with distroless
###
FROM gcr.io/distroless/nodejs@sha256:794e26246770ff28d285d7f800ce1982883cf4105662845689efa33f04ec4340 as distroless
FROM node:16-bullseye-slim as base

FROM gcr.io/distroless/nodejs20-debian12:latest@sha256:6499c05db574451eeddda4d3ddb374ac1aba412d6b2f5d215cc5e23c40c0e4d3 as distroless
FROM node:20-slim as base
ENV NODE_ENV=production
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
Expand All @@ -24,14 +27,6 @@ CMD ["nodemon", "./bin/www", "--inspect=0.0.0.0:9229"]
FROM base as source
COPY --chown=node:node . .

FROM source as test
ENV NODE_ENV=development
ENV PATH=/app/node_modules/.bin:$PATH
COPY --from=dev /app/node_modules /app/node_modules
RUN npx eslint .
RUN npm test
CMD ["npm", "run", "test"]

# switch to distroless for prod
# use version tags for always building with latest
# (more risky for stability, but likely more secure)
Expand Down
18 changes: 18 additions & 0 deletions dockerfiles/snyk.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

echo "[" > summary.json
for image in $(cat tags.txt); do
image_file=$(echo ${image} | tr '/' '-' | tr ':' '-')
tag=$(echo ${image} | cut -f 2 -d '/' | cut -f 2 -d ':')
echo "Testing ${image}..."

if [[ "$1" == "--no-cache" || ! -f snyk.${image_file}.json ]]; then
DOCKER_CLI_HINTS=false docker pull ${image}
snyk container test ${image} --exclude-app-vulns --json-file-output=snyk.${image_file}.json --group-issues > snyk.${image_file}.log
fi
summary=$(jq -c '[ .vulnerabilities[].severity] | reduce .[] as $sev ({}; .[$sev] +=1) | { image: "'${image}'", low: (.low // 0), medium: (.medium // 0), high: (.high // 0), critical: (.critical // 0)} | .total = .low + .medium + .high + .critical ' snyk.${image_file}.json)
echo " ${summary}," >> summary.json
done
echo "]" >> summary.json

cat summary.json
14 changes: 14 additions & 0 deletions dockerfiles/tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
node:20
node:20-slim
node:20-alpine
node:18
node:18-slim
node:18-alpine
debian:12
debian:12-slim
ubuntu:22.04
bretfisher/node:ubuntu-22.04-nodesource18
bretfisher/node:ubuntu-22.04-nodesource20
bretfisher/node:ubuntu-22.04-node20-copy
gcr.io/distroless/nodejs20-debian12
cgr.dev/chainguard/node:latest
19 changes: 9 additions & 10 deletions dockerfiles/ubuntu-copy.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
## ubuntu base with nodejs coppied in from official image, for a more secure base
###
#cache our node version for installing later
FROM node:16.14.2-slim as node
FROM ubuntu:focal-20220404 as base
#FROM node:20.7-slim as node
FROM node:18.18-slim as node
FROM ubuntu:lunar-20230816 as base

# replace npm in CMD with tini for better kernel signal handling
# You may also need development tools to build native npm addons:
Expand All @@ -21,18 +22,16 @@ COPY --from=node /usr/local/lib/ /usr/local/lib/
COPY --from=node /usr/local/bin/ /usr/local/bin/
RUN corepack disable && corepack enable

# create node user and group, then create app dir
RUN groupadd --gid 1000 node \
&& useradd --uid 1000 --gid node --shell /bin/bash --create-home node \
&& mkdir /app \
&& chown -R node:node /app
# create node user and group
RUN groupadd --gid 1001 node \
&& useradd --uid 1001 --gid node --shell /bin/bash --create-home node

# you'll likely need more stages for dev/test, but here's our basic prod layer with source code
FROM base as prod
EXPOSE 3000
WORKDIR /app
USER node
COPY --chown=node:node package*.json yarn*.lock ./
RUN npm ci --only=production && npm cache clean --force
WORKDIR /app
COPY --chown=node:node package*.json ./
RUN npm ci && npm cache clean --force
COPY --chown=node:node . .
CMD ["node", "./bin/www"]
Loading

0 comments on commit bf6de8d

Please sign in to comment.