From 34340510296eb907a40505537a31014f517b2933 Mon Sep 17 00:00:00 2001 From: sid palas Date: Tue, 21 Feb 2023 16:18:47 -0500 Subject: [PATCH] Port dev dockerfiles into stages --- .gitignore | 1 + .../api-node/.dockerignore | 3 +- .../client-react/.dockerignore | 3 +- .../api-golang/Dockerfile.8 | 72 +++++++++++++++++++ .../api-node/Dockerfile.9 | 51 +++++++++++++ 08-running-containers/Makefile | 2 +- 08-running-containers/docker-compose.yml | 4 +- .../api-golang/Dockerfile.dev | 18 ----- .../api-node/Dockerfile.dev | 15 ---- .../docker-compose-dev.yml | 20 +++++- 10 files changed, 148 insertions(+), 41 deletions(-) create mode 100644 06-building-container-images/api-golang/Dockerfile.8 create mode 100644 06-building-container-images/api-node/Dockerfile.9 delete mode 100644 11-development-workflow/api-golang/Dockerfile.dev delete mode 100644 11-development-workflow/api-node/Dockerfile.dev diff --git a/.gitignore b/.gitignore index 977fd82..05da328 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ **/node_modules +**/.npm *.un~ *.json~ diff --git a/05-example-web-application/api-node/.dockerignore b/05-example-web-application/api-node/.dockerignore index b512c09..5576ca5 100644 --- a/05-example-web-application/api-node/.dockerignore +++ b/05-example-web-application/api-node/.dockerignore @@ -1 +1,2 @@ -node_modules \ No newline at end of file +node_modules +.npm \ No newline at end of file diff --git a/05-example-web-application/client-react/.dockerignore b/05-example-web-application/client-react/.dockerignore index b512c09..5576ca5 100644 --- a/05-example-web-application/client-react/.dockerignore +++ b/05-example-web-application/client-react/.dockerignore @@ -1 +1,2 @@ -node_modules \ No newline at end of file +node_modules +.npm \ No newline at end of file diff --git a/06-building-container-images/api-golang/Dockerfile.8 b/06-building-container-images/api-golang/Dockerfile.8 new file mode 100644 index 0000000..ed976f0 --- /dev/null +++ b/06-building-container-images/api-golang/Dockerfile.8 @@ -0,0 +1,72 @@ +# Pin specific version for stability +# Use separate stage for building image +# Use debian for easier build utilities +FROM golang:1.19-bullseye AS base-builder + +# Add non root user +RUN useradd -u 1001 nonroot + +WORKDIR /app + +# Copy only files required to install dependencies (better layer caching) +COPY go.mod go.sum ./ + +# Use cache mount to speed up install of existing dependencies +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + go mod download + +# Dev stage with additional dev dependencies installed +FROM base-builder AS dev + +# Install air for hot reload & delve for debugging +RUN go install github.com/cosmtrek/air@latest && \ + go install github.com/go-delve/delve/cmd/dlv@latest + +COPY . . + +CMD ["air", "-c", ".air.toml"] + +# Production builder stage to produce the static binaries +FROM base-builder AS production-builder + +COPY . . + +# Compile healthcheck +RUN go build \ + -ldflags="-linkmode external -extldflags -static" \ + -tags netgo \ + -o healthcheck \ + ./healthcheck/healthcheck.go + +# Compile application during build rather than at runtime +# Add flags to statically link binary +RUN go build \ + -ldflags="-linkmode external -extldflags -static" \ + -tags netgo \ + -o api-golang + +# Use separate stage for deployable image +FROM scratch AS production + +# Set gin mode +ENV GIN_MODE=release + +WORKDIR / + +# Copy the passwd file +COPY --from=production-builder /etc/passwd /etc/passwd + +# Copy the healthcheck binary from the build stage +COPY --from=production-builder /app/healthcheck/healthcheck healthcheck + +# Copy the app binary from the build stage +COPY --from=production-builder /app/api-golang api-golang + +# Use nonroot user +USER nonroot + +# Indicate expected port +EXPOSE 8080 + +CMD ["/api-golang"] diff --git a/06-building-container-images/api-node/Dockerfile.9 b/06-building-container-images/api-node/Dockerfile.9 new file mode 100644 index 0000000..a6b2989 --- /dev/null +++ b/06-building-container-images/api-node/Dockerfile.9 @@ -0,0 +1,51 @@ +# Pin specific version for stability +# Use alpine for reduced image size +FROM node:19.6-alpine AS base + +# Set NODE_ENV +ENV NODE_ENV production + +# Specify working directory other than / +WORKDIR /usr/src/app + +# Copy only files required to install +# dependencies (better layer caching) +COPY package*.json ./ + +# Development stage to include dev + production dependencies +FROM base AS dev + +# Install all dependencies (including development ones) +# For the dev image +RUN --mount=type=cache,target=/usr/src/app/.npm \ + npm set cache /usr/src/app/.npm && \ + npm install + +COPY . . + +CMD [ "npm", "run", "dev" ] + +# Production stage optimzed for deployment +FROM base AS production + +# Install only production dependencies +# Use cache mount to speed up install of existing dependencies +RUN --mount=type=cache,target=/usr/src/app/.npm \ + npm set cache /usr/src/app/.npm && \ + npm ci --only=production + +# Use non-root user +# Use --chown on COPY commands to set file permissions +USER node + +# Copy the healthcheck script +COPY --chown=node:node ./healthcheck/ . + +# Copy remaining source code AFTER installing dependencies. +# Again, copy only the necessary files +COPY --chown=node:node ./src/ . + +# Indicate expected port +EXPOSE 3000 + +CMD [ "node", "index.js" ] diff --git a/08-running-containers/Makefile b/08-running-containers/Makefile index 190cd17..580e423 100644 --- a/08-running-containers/Makefile +++ b/08-running-containers/Makefile @@ -84,7 +84,7 @@ docker-run-all: docker run -d \ --name client-react-nginx \ --network my-network \ - -p 5174:80 \ + -p 80:8080 \ --restart unless-stopped \ --link=api-node \ --link=api-golang \ diff --git a/08-running-containers/docker-compose.yml b/08-running-containers/docker-compose.yml index 2ab0609..7856bc5 100644 --- a/08-running-containers/docker-compose.yml +++ b/08-running-containers/docker-compose.yml @@ -3,7 +3,7 @@ services: image: client-react-vite build: context: ../05-example-web-application/client-react/ - dockerfile: ../../06-building-container-images/client-react/Dockerfile.4 + dockerfile: ../../06-building-container-images/client-react/Dockerfile.3 init: true volumes: - ${PWD}/client-react/vite.config.js:/usr/src/app/vite.config.js @@ -26,7 +26,7 @@ services: image: api-node build: context: ../05-example-web-application/api-node/ - dockerfile: ../../06-building-container-images/api-node/Dockerfile.8 + dockerfile: ../../06-building-container-images/api-node/Dockerfile.7 init: true depends_on: - db diff --git a/11-development-workflow/api-golang/Dockerfile.dev b/11-development-workflow/api-golang/Dockerfile.dev deleted file mode 100644 index 28b6155..0000000 --- a/11-development-workflow/api-golang/Dockerfile.dev +++ /dev/null @@ -1,18 +0,0 @@ -# Using bullseye instead of alpine because debugger didnt work in alpine -FROM golang:1.19-bullseye - -WORKDIR /app - -# Install air for hot reload -RUN go install github.com/cosmtrek/air@latest - -# Install delve for debugging -RUN go install github.com/go-delve/delve/cmd/dlv@latest - -COPY go.mod go.sum ./ - -RUN go mod download - -COPY . . - -CMD ["air", "-c", ".air.toml"] diff --git a/11-development-workflow/api-node/Dockerfile.dev b/11-development-workflow/api-node/Dockerfile.dev deleted file mode 100644 index b0577b2..0000000 --- a/11-development-workflow/api-node/Dockerfile.dev +++ /dev/null @@ -1,15 +0,0 @@ -FROM node:19.4-alpine as dev - -WORKDIR /usr/src/app - -COPY package*.json ./ - -RUN --mount=type=cache,target=/usr/src/app/.npm \ - npm set cache /usr/src/app/.npm && \ - npm install - -COPY . . - -EXPOSE 3000 - -CMD [ "npm", "run", "dev" ] diff --git a/11-development-workflow/docker-compose-dev.yml b/11-development-workflow/docker-compose-dev.yml index cb6e938..05258cd 100644 --- a/11-development-workflow/docker-compose-dev.yml +++ b/11-development-workflow/docker-compose-dev.yml @@ -3,6 +3,8 @@ services: build: context: ../05-example-web-application/client-react/ dockerfile: ../../06-building-container-images/client-react/Dockerfile.3 + networks: + - frontend ports: - 5173:5173 volumes: @@ -18,7 +20,7 @@ services: api-node: build: context: ../05-example-web-application/api-node/ - dockerfile: ../../11-development-workflow/api-node/Dockerfile.dev + dockerfile: ../../06-building-container-images/api-node/Dockerfile.9 target: dev volumes: - type: bind @@ -31,13 +33,17 @@ services: - db environment: - DATABASE_URL=postgres://postgres:foobarbaz@db:5432/postgres + networks: + - frontend + - backend ports: - "3000:3000" restart: unless-stopped api-golang: build: context: ../05-example-web-application/api-golang/ - dockerfile: ../../11-development-workflow/api-golang/Dockerfile.dev + dockerfile: ../../06-building-container-images/api-golang/Dockerfile.8 + target: dev volumes: - type: bind source: ../05-example-web-application/api-golang/ @@ -47,6 +53,9 @@ services: - db environment: - DATABASE_URL=postgres://postgres:foobarbaz@db:5432/postgres + networks: + - frontend + - backend ports: - "8080:8080" restart: unless-stopped @@ -56,7 +65,12 @@ services: - pgdata:/var/lib/postgresql/data environment: - POSTGRES_PASSWORD=foobarbaz + networks: + - backend ports: - 5432:5432 volumes: - pgdata: \ No newline at end of file + pgdata: +networks: + frontend: + backend: \ No newline at end of file