Skip to content

Instantly share code, notes, and snippets.

@gigiperih
Created January 13, 2022 16:25
Show Gist options
  • Save gigiperih/964442ea3c2958c67ffd2e64085f53c8 to your computer and use it in GitHub Desktop.
Save gigiperih/964442ea3c2958c67ffd2e64085f53c8 to your computer and use it in GitHub Desktop.
Dockerize: production ready next-js app (turborepo, watchtower, shoutrrr, nginx, ssl)
version: '2'
services:
web-app:
image: index.docker.io/{org}/{image}:latest
container_name: "name"
ports:
- "3000:3000"
environment:
VIRTUAL_HOST: "your.host.com"
LETSENCRYPT_HOST: "your.host.com"
LETSENCRYPT_EMAIL: "[email protected]"
nginx-proxy:
image: jwilder/nginx-proxy
container_name: nginx-proxy
ports:
- '80:80'
- '443:443'
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- /etc/nginx/vhost.d
- /usr/share/nginx/html
- /apps/web/ssl:/etc/nginx/certs:ro
# ini juara sekaliiiii.. mempercepat segalanya, save up your time
ssl-companion:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: ssl-companion
volumes:
- /apps/web/ssl:/etc/nginx/certs:rw
- /var/run/docker.sock:/var/run/docker.sock:ro
volumes_from:
- nginx-proxy
depends_on:
- nginx-proxy
# image watcher
# will pull and restart container when update ready from docker hub channel
watchtower:
image: containrrr/watchtower
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /etc/timezone:/etc/timezone:ro
- ~/.docker/config.json:/config.json
environment:
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_LABEL_ENABLE=true
- WATCHTOWER_INCLUDE_RESTARTING=true
- WATCHTOWER_NOTIFICATION_URL=discord://{token}@{channelId}?SplitLines=false
- WATCHTOWER_NOTIFICATIONS=shoutrrr
labels:
- "com.centurylinklabs.watchtower.enable=true"
command: --interval 666
#
# EXAMPLE OF MULTISTAGE BUILD FOR MONOREPOS
#
# @link https://github.com/belgattitude/nextjs-monorepo-example
#
###################################################################
# Stage 1: Install all workspaces (dev)dependencies #
# and generates node_modules folder(s) #
# ----------------------------------------------------------------#
# Notes: #
# 1. this stage relies on buildkit features #
# 2. depend on .dockerignore, you must at least #
# ignore: all **/node_modules folders and .yarn/cache #
###################################################################
ARG NODE_VERSION=16
ARG ALPINE_VERSION=3.14
FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION} AS deps
RUN apk add --no-cache rsync
WORKDIR /workspace-install
COPY yarn.lock ./
# Specific to monerepo's as docker COPY command is pretty limited
# we use buidkit to prepare all files that are necessary for install
# and that will be used to invalidate docker cache.
#
# Files are copied with rsync:
#
# - All package.json present in the host (root, apps/*, packages/*)
# - All schema.prisma (cause prisma will generate a schema on postinstall)
#
RUN --mount=type=bind,target=/docker-context \
rsync -amv --delete \
--exclude='node_modules' \
--exclude='*/node_modules' \
--include='package.json' \
--include='*/' --exclude='*' \
/docker-context/ /workspace-install/;
# @see https://www.prisma.io/docs/reference/api-reference/environment-variables-reference#cli-binary-targets
ENV PRISMA_CLI_BINARY_TARGETS=linux-musl
#
# To speed up installations, we override the default yarn cache folder
# and mount it as a buildkit cache mount (builkit will rotate it if needed)
# This strategy allows to exclude the yarn cache in subsequent docker
# layers (size benefit) and reduce packages fetches.
#
# PS:
# 1. Cache mounts can be used in CI (github actions)
# 2. To manually clear the cache
# > docker builder prune --filter type=exec.cachemount
#
RUN --mount=type=cache,target=/root/.yarn-cache \
YARN_CACHE_FOLDER=/root/.yarn-cache \
yarn install --immutable --inline-builds
###################################################################
# Stage 2: Build the app #
###################################################################
FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION} AS builder
ENV NODE_ENV=production
ENV NEXTJS_IGNORE_ESLINT=1
ENV NEXTJS_IGNORE_TYPECHECK=0
WORKDIR /app
COPY . .
COPY --from=deps /workspace-install ./
# Optional: if the app depends on global /static shared assets like images, locales...
RUN yarn workspace web build
#RUN --mount=type=cache,target=/root/.yarn-cache,id=workspace-install,rw \
# SKIP_POSTINSTALL=1 \
# YARN_CACHE_FOLDER=/root/.yarn-cache \
# yarn workspaces focus web --production
###################################################################
# Stage 3: Extract a minimal image from the build #
###################################################################
FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION} AS runner
WORKDIR /app
ENV NODE_ENV production
RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001
COPY --from=builder /app/apps/web/next.config.js \
/app/apps/web/postcss.config.js \
/app/apps/web/jest.config.js \
/app/apps/web/tailwind.config.js \
/app/apps/web/package.json \
./apps/web/
COPY --from=builder /app/apps/web/public ./apps/web/public
COPY --from=builder --chown=nextjs:nodejs /app/apps/web/.next ./apps/web/.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
USER nextjs
EXPOSE ${WEB_APP_PORT:-3000}
ENV NEXT_TELEMETRY_DISABLED 1
LABEL "com.centurylinklabs.watchtower.enable"="true"
# https://github.com/vercel/next.js/issues/9870
CMD ["./node_modules/next/dist/bin/next", "start", "apps/web/", "-p", "${WEB_APP_PORT:-3000}"]
# docker run --name temulawak -d -p 3000:3000 sadabhumi-monorepo:300
###################################################################
# Optional: develop locally #
###################################################################
#FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION} AS develop
#ENV NODE_ENV=development
#
#WORKDIR /app
#
#COPY --from=deps /workspace-install ./
#
#EXPOSE ${WEB_APP_PORT:-3000}
#
#WORKDIR /app/apps/web-app
#
#CMD ["yarn", "dev", "-p", "${WEB_APP_PORT:-3000}"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment