diff --git a/.env.default b/.env.default new file mode 100644 index 000000000..b78b5599a --- /dev/null +++ b/.env.default @@ -0,0 +1,18 @@ +# Please copy and rename this file. +# +# !Attention! +# Always ensure to load the env variables in every terminal session. +# Otherwise the env variables will not be available + +DOCKER_COMPOSE_APP_DEV_PORT_PUBLISHED=9001 +DOCKER_COMPOSE_APP_DEV_PORT_TARGET=9001 + +# IMPORTANT: When the env var DEFAULT_PAD_TEXT is unset or empty, then the pad is not established (not the landing page). +# The env var DEFAULT_PAD_TEXT seems to be mandatory in the latest version of etherpad. +DOCKER_COMPOSE_APP_DEV_ENV_DEFAULT_PAD_TEXT="Welcome to etherpad" + +DOCKER_COMPOSE_APP_DEV_ADMIN_PASSWORD= + +DOCKER_COMPOSE_POSTGRES_DEV_ENV_POSTGRES_DATABASE=db +DOCKER_COMPOSE_POSTGRES_DEV_ENV_POSTGRES_PASSWORD=etherpad-lite-password +DOCKER_COMPOSE_POSTGRES_DEV_ENV_POSTGRES_USER=etherpad-lite-user \ No newline at end of file diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 9909d9583..2edf31cee 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -30,6 +30,7 @@ jobs: uses: docker/build-push-action@v5 with: context: . + target: production load: true tags: ${{ env.TEST_TAG }} cache-from: type=gha @@ -97,6 +98,7 @@ jobs: uses: docker/build-push-action@v5 with: context: . + target: production platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.meta.outputs.tags }} diff --git a/.gitignore b/.gitignore index cb81fbc85..5364f4397 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ node_modules APIKEY.txt SESSIONKEY.txt var/dirty.db +.env *~ *.patch npm-debug.log diff --git a/Dockerfile b/Dockerfile index ff6417001..a50d6bca5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ # # Author: muxator -FROM node:alpine AS builder +FROM node:alpine as build LABEL maintainer="Etherpad team, https://github.com/ether/etherpad-lite" ARG TIMEZONE= @@ -44,11 +44,6 @@ ARG INSTALL_ABIWORD= # INSTALL_LIBREOFFICE=true ARG INSTALL_SOFFICE= -# By default, Etherpad container is built and run in "production" mode. This is -# leaner (development dependencies are not installed) and runs faster (among -# other things, assets are minified & compressed). -ENV NODE_ENV=production -ENV ETHERPAD_PRODUCTION=true # Install dependencies required for modifying access. RUN apk add shadow bash # Follow the principle of least privilege: run as unprivileged user. @@ -63,9 +58,6 @@ ARG EP_UID=5001 ARG EP_GID=0 ARG EP_SHELL= -ARG NODE_ENV -ENV NODE_ENV=${NODE_ENV:-production} - RUN groupadd --system ${EP_GID:+--gid "${EP_GID}" --non-unique} etherpad && \ useradd --system ${EP_UID:+--uid "${EP_UID}" --non-unique} --gid etherpad \ ${EP_HOME:+--home-dir "${EP_HOME}"} --create-home \ @@ -74,7 +66,6 @@ RUN groupadd --system ${EP_GID:+--gid "${EP_GID}" --non-unique} etherpad && \ ARG EP_DIR=/opt/etherpad-lite RUN mkdir -p "${EP_DIR}" && chown etherpad:etherpad "${EP_DIR}" -USER root # the mkdir is needed for configuration of openjdk-11-jre-headless, see # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=863199 RUN \ @@ -92,7 +83,31 @@ USER etherpad WORKDIR "${EP_DIR}" -COPY --chown=etherpad:etherpad ./ ./ +# etherpads version feature requires this. Only copy what is really needed +COPY --chown=etherpad:etherpad ./.git/HEAD ./.git/HEAD +COPY --chown=etherpad:etherpad ./.git/refs ./.git/refs +COPY --chown=etherpad:etherpad ${SETTINGS} ./settings.json +COPY --chown=etherpad:etherpad ./var ./var +COPY --chown=etherpad:etherpad ./node_modules ./node_modules + +FROM build as development + +COPY --chown=etherpad:etherpad ./src/package.json .npmrc ./src/pnpm-lock.yaml ./src/ +COPY --chown=etherpad:etherpad ./src/bin ./src/bin + +RUN { [ -z "${ETHERPAD_PLUGINS}" ] || \ + pnpm install --no-save --legacy-peer-deps ${ETHERPAD_PLUGINS}; } && \ + src/bin/installDeps.sh + +FROM build as production + +# By default, Etherpad container is built and run in "production" mode. This is +# leaner (development dependencies are not installed) and runs faster (among +# other things, assets are minified & compressed). +ENV NODE_ENV=production +ENV ETHERPAD_PRODUCTION=true + +COPY --chown=etherpad:etherpad ./src ./src # Plugins must be installed before installing Etherpad's dependencies, otherwise # npm will try to hoist common dependencies by removing them from @@ -103,7 +118,7 @@ COPY --chown=etherpad:etherpad ./ ./ # seems to confuse tools such as `npm outdated`, `npm update`, and some ESLint # rules. RUN { [ -z "${ETHERPAD_PLUGINS}" ] || \ - npm install --no-save --legacy-peer-deps ${ETHERPAD_PLUGINS}; } && \ + pnpm install --no-save --legacy-peer-deps ${ETHERPAD_PLUGINS}; } && \ src/bin/installDeps.sh && \ rm -rf ~/.npm @@ -111,15 +126,13 @@ RUN { [ -z "${ETHERPAD_PLUGINS}" ] || \ COPY --chown=etherpad:etherpad ${SETTINGS} "${EP_DIR}"/settings.json # Fix group permissions -#RUN chmod -R g=u . - -USER root +# Note: For some reason increases image size from 257 to 334. +# RUN chmod -R g=u . USER etherpad -WORKDIR /opt/etherpad-lite - HEALTHCHECK --interval=5s --timeout=3s \ - CMD curl --silent http://localhost:9001/health | grep -E "pass|ok|up" > /dev/null || exit 1 + CMD curl --silent http://localhost:9001/health | grep -E "pass|ok|up" > /dev/null || exit 1 + EXPOSE 9001 CMD ["npm", "run", "prod", "--prefix", "./src"] diff --git a/doc/docker.adoc b/doc/docker.adoc index 5f4b78120..ec5277f80 100644 --- a/doc/docker.adoc +++ b/doc/docker.adoc @@ -20,6 +20,37 @@ If you want to use a personalized settings file, **you will have to rebuild your All of the following instructions are as a member of the `docker` group. By default, the Etherpad Docker image is built and run in `production` mode: no development dependencies are installed, and asset bundling speeds up page load time. +=== Building and running with docker compose +A docker compose file is provided in the project. Please first copy `.env.default` to `.env` and adjust the variables to your preference. + +``` +docker compose up -d # will build and start the docker container on port 9001 with development settings. +``` + +Starting dev server: + +``` +docker compose exec app bash -c "./src/bin/run.sh" +``` + +For production, please create your own docker compose file and change the `target` property in the build section to `production`. In addition, change the NODE_ENV in environment to production. For instance: + +``` +docker compose -f docker-compose-production.yml up -d +``` + +For plugins, please add them in the build section under ETHERPAD_PLUGINS, for instance: + +``` + args: + ETHERPAD_PLUGINS: >- + ep_image_upload + ep_embedded_hyperlinks2 + ep_headings2 + ep_align + ... +``` + ==== Rebuilding with custom settings Edit `/settings.json.docker` at your will. When rebuilding the image, this file will be copied inside your image and renamed to `settings.json`. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..bb4ac85ee --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,64 @@ +version: "3.8" + +# Add this file to extend the docker-compose setup, e.g.: +# docker-compose build --no-cache +# docker-compose up -d --build --force-recreate + +services: + app: + build: + context: . + args: + ETHERPAD_PLUGINS: + # change from development to production if needed + target: development + tty: true + stdin_open: true + volumes: + - ./src:/opt/etherpad-lite/src + - node_modules:/opt/etherpad-lite/src/node_modules + - pnpm-store:/home/etherpad/.local/share/pnpm/store/v3 + depends_on: + - postgres + environment: + # change from development to production if needed + NODE_ENV: development + ADMIN_PASSWORD: ${DOCKER_COMPOSE_APP_DEV_ADMIN_PASSWORD} + DB_CHARSET: ${DOCKER_COMPOSE_APP_DEV_ENV_DB_CHARSET:-utf8mb4} + DB_HOST: postgres + DB_NAME: ${DOCKER_COMPOSE_POSTGRES_DEV_ENV_POSTGRES_DATABASE:?} + DB_PASS: ${DOCKER_COMPOSE_POSTGRES_DEV_ENV_POSTGRES_PASSWORD:?} + DB_PORT: ${DOCKER_COMPOSE_POSTGRES_DEV_ENV_POSTGRES_PORT:-5432} + DB_TYPE: "postgres" + DB_USER: ${DOCKER_COMPOSE_POSTGRES_DEV_ENV_POSTGRES_USER:?} + # For now, the env var DEFAULT_PAD_TEXT cannot be unset or empty; it seems to be mandatory in the latest version of etherpad + DEFAULT_PAD_TEXT: ${DOCKER_COMPOSE_APP_DEV_ENV_DEFAULT_PAD_TEXT:- } + DISABLE_IP_LOGGING: ${DOCKER_COMPOSE_APP_DEV_ENV_DISABLE_IP_LOGGING:-true} + SOFFICE: ${DOCKER_COMPOSE_APP_DEV_ENV_SOFFICE:-null} + TRUST_PROXY: ${DOCKER_COMPOSE_APP_DEV_ENV_TRUST_PROXY:-true} + restart: always + ports: + - "${DOCKER_COMPOSE_APP_DEV_PORT_PUBLISHED:-9001}:${DOCKER_COMPOSE_APP_DEV_PORT_TARGET:-9001}" + + postgres: + image: postgres:15-alpine + # Pass config parameters to the mysql server. + # Find more information below when you need to generate the ssl-relevant file your self + environment: + POSTGRES_DB: ${DOCKER_COMPOSE_POSTGRES_DEV_ENV_POSTGRES_DATABASE:?} + POSTGRES_PASSWORD: ${DOCKER_COMPOSE_POSTGRES_DEV_ENV_POSTGRES_PASSWORD:?} + POSTGRES_PORT: ${DOCKER_COMPOSE_POSTGRES_DEV_ENV_POSTGRES_PORT:-5432} + POSTGRES_USER: ${DOCKER_COMPOSE_POSTGRES_DEV_ENV_POSTGRES_USER:?} + PGDATA: /var/lib/postgresql/data/pgdata + restart: always + # Exposing the port is not needed unless you want to access this database instance from the host. + # Be careful when other postgres docker container are running on the same port + # ports: + # - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data/pgdata + +volumes: + postgres_data: + node_modules: + pnpm-store: \ No newline at end of file