diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..7f595488e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) +# +# SPDX-License-Identifier: CC0-1.0 + +dist + +# Yarn 2 without zero-installs +.yarn/* +!.yarn/patches +!.yarn/releases +!.yarn/plugins +!.yarn/sdks +!.yarn/versions +.pnp.* diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 000000000..4447ecd32 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,75 @@ +# SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) +# SPDX-License-Identifier: AGPL-3.0-only +# +# This Dockerfile uses features which are only available in BuildKit - see +# https://docs.docker.com/go/buildkit/ for more information. +# +# To build the image, run `docker build` command from the root of the +# repository: +# +# DOCKER_BUILDKIT=1 docker build -f docker/Dockerfile . + +## Stage 0: Base image with only yarn and package.json +FROM docker.io/node:16-alpine as base +# Add tini to handle signals +# https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#handling-kernel-signals +RUN apk add --no-cache tini +ENTRYPOINT ["tini"] + +USER node +WORKDIR /usr/src/app + +COPY --chown=node .yarn .yarn +COPY --chown=node package.json yarn.lock .yarnrc.yml ./ + + +## Stage 1: Code with all dependencies +FROM base as code-with-deps +USER node +WORKDIR /usr/src/app + +# Install dependencies first to not invalidate the cache on every source change +RUN --mount=type=cache,sharing=locked,uid=1000,gid=1000,target=/tmp/.yarn \ + YARN_CACHE_FOLDER=/tmp/.yarn yarn install --immutable + +COPY --chown=node nest-cli.json tsconfig.json tsconfig.build.json ./ +COPY --chown=node src src + + +## Stage 2a: Dev config files and tests +FROM code-with-deps as development +USER node +WORKDIR /usr/src/app + +COPY --chown=node .eslintrc.js eslint-local-rules.js .prettierrc jest-e2e.json ./ +COPY --chown=node test test + +CMD ["node", "-r", "ts-node/register", "src/main.ts"] + +## Stage 2b: Compile TypeScript +FROM code-with-deps as builder +USER node +WORKDIR /usr/src/app + +RUN yarn run build + + +## Stage 3: Final image, only production dependencies +FROM base as prod + +LABEL org.opencontainers.image.title='HedgeDoc production image' +LABEL org.opencontainers.image.url='https://hedgedoc.org' +LABEL org.opencontainers.image.source='https://github.com/hedgedoc/hedgedoc' +LABEL org.opencontainers.image.documentation='https://github.com/hedgedoc/hedgedoc/blob/develop/docker/README.md' +LABEL org.opencontainers.image.licenses='AGPL-3.0' + +USER node +WORKDIR /usr/src/app +ENV NODE_ENV=production + +COPY --chown=node --from=builder /usr/src/app/dist ./dist + +RUN --mount=type=cache,sharing=locked,uid=1000,gid=1000,target=/tmp/.yarn \ + YARN_CACHE_FOLDER=/tmp/.yarn yarn workspaces focus --all --production + +CMD ["node", "dist/main.js"] diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 000000000..a1e2d44a4 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,32 @@ + + +# Using HedgeDoc with Docker + +**Important:** This README does **not** refer to HedgeDoc 1. For setting up HedgeDoc 1 with Docker, see https://docs.hedgedoc.org/setup/docker/. + +The `Dockerfile` in this repo uses multiple stages and can be used to create both images for development +and images with only production dependencies. +It uses features which are only available in BuildKit - see https://docs.docker.com/go/buildkit/ for more information. + +## Build a production image +**Note:** This does not include any frontend! + +To build a production image, run the following command *from the root of the repository*: +`docker build -t hedgedoc-prod -f docker/Dockerfile .` + +When you run the image, you need to provide environment variables to configure HedgeDoc. +See [the config docs](../docs/content/config/index.md) for more information. +This example starts HedgeDoc on localhost, with non-persistent storage: +`docker run -e HD_DOMAIN=http://localhost -e HD_MEDIA_BACKEND=filesystem -e HD_MEDIA_BACKEND_FILESYSTEM_UPLOAD_PATH=uploads -e HD_DATABASE_DIALECT=sqlite -e HD_DATABASE_STORAGE=hedgedoc.sqlite -e HD_SESSION_SECRET=foobar -e HD_LOGLEVEL=debug -p 3000:3000 hedgedoc-prod` + + +## Build a development image +You can build a development image using the `development` target: +`docker build -t hedgedoc-dev -f docker/Dockerfile --target development .` + +You can then, e.g. run tests inside the image: +`docker run hedgedoc-dev yarn run test:e2e`