Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Small docker improvements and fixes #12335

Merged
merged 23 commits into from May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3b98ccb
feat: disable uneecessary npm features
oplik0 Feb 10, 2024
d81d560
fix: make default actually defaults not forced values
oplik0 Feb 10, 2024
511cad9
feat: upgrade on container changes
oplik0 Feb 10, 2024
8278f87
feat: support changing build verb
oplik0 Feb 10, 2024
29b5f9c
fix: use local volumes instead of bind mounts
oplik0 Feb 10, 2024
b78e8fc
fix: save just the hash without any unexpected whitespace
oplik0 Feb 11, 2024
354f5b2
feat: use run with mount instead of copying for cross-platfomr builds
oplik0 Feb 27, 2024
cb6b2e5
ci: try with minimal cache
oplik0 Feb 27, 2024
805265f
ci: don't fetch all branches
oplik0 Feb 27, 2024
1130716
feat: bsic support for other package managers via PACKAGE_MANAGER env…
oplik0 Feb 27, 2024
8d2c029
refactor: better structured entrypoint
oplik0 Mar 14, 2024
9071500
ci: properly cache the node_modules mount
oplik0 Mar 14, 2024
f6c6c07
fix: syntax error
oplik0 Mar 14, 2024
3854132
refactor: fine tune docker-related files
NavyStack Mar 15, 2024
bd7b3e9
Merge branch 'master' into small-docker-improvements
NavyStack Mar 15, 2024
8541de8
ci: docker image taging (time, latest)
NavyStack Mar 15, 2024
af8ca8a
fix: remove the trailing slash for correct directory path
NavyStack Mar 15, 2024
cb9c62b
docker: todo- use environment variables to create files
NavyStack Mar 15, 2024
4e74996
docker: fix permissions
NavyStack Mar 19, 2024
515ae66
docker: fix permissions
NavyStack Mar 19, 2024
2e9443f
docker: fix stage
NavyStack Mar 19, 2024
2f1e750
feat: auto-upgrade on package.json changes
oplik0 May 9, 2024
86739e6
fix: don't profile-gate postgres
oplik0 May 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Empty file added .docker/.gitkeep
Empty file.
Empty file added .docker/build/.gitkeep
Empty file.
Empty file added .docker/config/.gitkeep
Empty file.
Empty file.
Empty file.
Empty file.
Empty file added .docker/public/uploads/.gitkeep
Empty file.
17 changes: 14 additions & 3 deletions .github/workflows/docker.yml
Expand Up @@ -21,8 +21,6 @@ jobs:
steps:

- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up QEMU
uses: docker/setup-qemu-action@v3
Expand All @@ -37,6 +35,9 @@ jobs:
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Get current date in NST
run: echo "CURRENT_DATE_NST=$(date +'%Y%m%d-%H%M%S' -d '-3 hours -30 minutes')" >> $GITHUB_ENV

- name: Docker meta
id: meta
uses: docker/metadata-action@v5
Expand All @@ -48,12 +49,22 @@ jobs:
type=semver,pattern={{major}}.x
type=raw,value=latest,enable={{is_default_branch}}
type=ref,event=branch,enable=${{ github.event.repository.default_branch != github.ref }}
type=raw,value=${{ env.CURRENT_DATE_NST }}
flavor: |
latest=true

- name: Cache node_modules
id: cache-node-modules
uses: actions/cache@v3
with:
path: var-cache-node-modules
key: var-cache-node-modules-${{ hashFiles('Dockerfile', 'install/package.json') }}

- name: Build and push Docker images
uses: docker/build-push-action@v5
with:
cache-from: type=gha
cache-to: type=gha,mode=max
cache-to: type=gha,mode=min
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/arm/v7
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Expand Up @@ -71,4 +71,5 @@ package-lock.json
link-plugins.sh
test.sh

.docker/
.docker/**
!**/.gitkeep
87 changes: 55 additions & 32 deletions Dockerfile
@@ -1,51 +1,74 @@
FROM --platform=$BUILDPLATFORM node:lts as npm
FROM node:lts as build

RUN mkdir -p /usr/src/build && \
chown -R node:node /usr/src/build
WORKDIR /usr/src/build
ENV NODE_ENV=production \
DAEMON=false \
SILENT=false \
USER=nodebb \
UID=1001 \
GID=1001

ARG NODE_ENV
ENV NODE_ENV $NODE_ENV
WORKDIR /usr/src/app/

COPY --chown=node:node install/package.json /usr/src/build/package.json
COPY . /usr/src/app/

USER node
# Install corepack to allow usage of other package managers
RUN corepack enable

RUN npm install --omit=dev

FROM node:lts as rebuild
# Removing unnecessary files for us
RUN find . -mindepth 1 -maxdepth 1 -name '.*' ! -name '.' ! -name '..' -exec bash -c 'echo "Deleting {}"; rm -rf {}' \;

ARG BUILDPLATFORM
ARG TARGETPLATFORM
# Prepage package.json
RUN cp /usr/src/app/install/package.json /usr/src/app/

RUN mkdir -p /usr/src/build && \
chown -R node:node /usr/src/build
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive \
apt-get -y --no-install-recommends install \
tini

COPY --from=npm /usr/src/build /usr/src/build
RUN groupadd --gid ${GID} ${USER} \
&& useradd --uid ${UID} --gid ${GID} --home-dir /usr/src/app/ --shell /bin/bash ${USER} \
&& chown -R ${USER}:${USER} /usr/src/app/

RUN if [ $BUILDPLATFORM != $TARGETPLATFORM ]; then \
npm rebuild && \
npm cache clean --force; fi
USER ${USER}

FROM node:lts-slim as run
RUN npm install --omit=dev
# TODO: generate lockfiles for each package manager
## pnpm import \

ARG NODE_ENV
ENV NODE_ENV=$NODE_ENV \
daemon=false \
silent=false
FROM node:lts-slim AS final

RUN mkdir -p /usr/src/app && \
chown -R node:node /usr/src/app
ENV NODE_ENV=production \
DAEMON=false \
SILENT=false \
USER=nodebb \
UID=1001 \
GID=1001

COPY --chown=node:node --from=rebuild /usr/src/build /usr/src/app
WORKDIR /usr/src/app/

COPY --from=build --chown=${USER}:${USER} /usr/src/app/ /usr/src/app/install/docker/setup.json /usr/src/app/
COPY --from=build --chown=${USER}:${USER} /usr/bin/tini /usr/src/app/install/docker/entrypoint.sh /usr/local/bin/

WORKDIR /usr/src/app
RUN corepack enable \
&& groupadd --gid ${GID} ${USER} \
&& useradd --uid ${UID} --gid ${GID} --home-dir /usr/src/app/ --shell /bin/bash ${USER} \
&& mkdir -p /usr/src/app/logs/ /opt/config/ \
&& chown -R ${USER}:${USER} /usr/src/app/ /opt/config/ \
&& chmod +x /usr/local/bin/entrypoint.sh \
&& chmod +x /usr/local/bin/tini

USER node
# TODO: Have docker-compose use environment variables to create files like setup.json and config.json.
# COPY --from=hairyhenderson/gomplate:stable /gomplate /usr/local/bin/gomplate

COPY --chown=node:node . /usr/src/app
USER ${USER}

EXPOSE 4567
VOLUME ["/usr/src/app/node_modules", "/usr/src/app/build", "/usr/src/app/public/uploads", "/opt/config"]
ENTRYPOINT ["./install/docker/entrypoint.sh"]

VOLUME ["/usr/src/app/node_modules", "/usr/src/app/build", "/usr/src/app/public/uploads", "/opt/config/"]

# Utilising tini as our init system within the Docker container for graceful start-up and termination.
# Tini serves as an uncomplicated init system, adept at managing the reaping of zombie processes and forwarding signals.
# This approach is crucial to circumvent issues with unmanaged subprocesses and signal handling in containerised environments.
# By integrating tini, we enhance the reliability and stability of our Docker containers.
# Ensures smooth start-up and shutdown processes, and reliable, safe handling of signal processing.
ENTRYPOINT ["tini", "--", "entrypoint.sh"]
76 changes: 76 additions & 0 deletions dev.Dockerfile
@@ -0,0 +1,76 @@
FROM node:lts AS git

ENV USER=nodebb \
UID=1001 \
GID=1001

WORKDIR /usr/src/app/

RUN groupadd --gid ${GID} ${USER} \
&& useradd --uid ${UID} --gid ${GID} --home-dir /usr/src/app/ --shell /bin/bash ${USER} \
&& chown -R ${USER}:${USER} /usr/src/app/

RUN apt-get update \
&& apt-get -y --no-install-recommends install tini

USER ${USER}

# Change to the git branch you want to test
RUN git clone --recurse-submodules -j8 --depth 1 https://github.com/NodeBB/NodeBB.git .

RUN find . -mindepth 1 -maxdepth 1 -name '.*' ! -name '.' ! -name '..' -exec bash -c 'echo "Deleting {}"; rm -rf {}' \;

FROM node:lts AS node_modules_touch

ENV NODE_ENV=development \
USER=nodebb \
UID=1001 \
GID=1001

WORKDIR /usr/src/app/

RUN corepack enable \
&& groupadd --gid ${GID} ${USER} \
&& useradd --uid ${UID} --gid ${GID} --home-dir /usr/src/app/ --shell /bin/bash ${USER} \
&& chown -R ${USER}:${USER} /usr/src/app/

COPY --from=git --chown=${USER}:${USER} /usr/src/app/install/package.json /usr/src/app/

USER ${USER}

RUN npm install

FROM node:lts-slim AS final

ENV NODE_ENV=development \
DAEMON=false \
SILENT=false \
USER=nodebb \
UID=1001 \
GID=1001

WORKDIR /usr/src/app/

COPY --from=build --chown=${USER}:${USER} /usr/src/app/ /usr/src/app/install/docker/setup.json /usr/src/app/
COPY --from=build --chown=${USER}:${USER} /usr/bin/tini /usr/src/app/install/docker/entrypoint.sh /usr/local/bin/
COPY --from=node_modules_touch --chown=${USER}:${USER} /usr/src/app/ /usr/src/app/
COPY --from=git --chown=${USER}:${USER} /usr/src/app/ /usr/src/app/

RUN corepack enable \
&& groupadd --gid ${GID} ${USER} \
&& useradd --uid ${UID} --gid ${GID} --home-dir /usr/src/app/ --shell /bin/bash ${USER} \
&& mkdir -p /usr/src/app/logs/ /opt/config/ \
&& chown -R ${USER}:${USER} /usr/src/app/ /opt/config/ \
&& chmod +x /usr/local/bin/entrypoint.sh \
&& chmod +x /usr/local/bin/tini

# TODO: Have docker-compose use environment variables to create files like setup.json and config.json.
# COPY --from=hairyhenderson/gomplate:stable /gomplate /usr/local/bin/gomplate

USER ${USER}

EXPOSE 4567

VOLUME ["/usr/src/app/node_modules", "/usr/src/app/build", "/usr/src/app/public/uploads", "/opt/config/"]

ENTRYPOINT ["tini", "--", "entrypoint.sh"]
68 changes: 68 additions & 0 deletions docker-compose-pgsql.yml
@@ -0,0 +1,68 @@
version: '3.8'

services:
nodebb:
build: .
# image: ghcr.io/nodebb/nodebb:latest
restart: unless-stopped
ports:
- '4567:4567' # comment this out if you don't want to expose NodeBB to the host, or change the first number to any port you want
volumes:
- nodebb-build:/usr/src/app/build
- nodebb-uploads:/usr/src/app/public/uploads
- nodebb-config:/opt/config
- ./install/docker/setup.json:/usr/src/app/setup.json

postgres:
image: postgres:16.1-alpine
restart: unless-stopped
environment:
POSTGRES_USER: nodebb
POSTGRES_PASSWORD: nodebb
POSTGRES_DB: nodebb
volumes:
- postgres-data:/var/lib/postgresql/data

redis:
image: redis:7.2.3-alpine
restart: unless-stopped
command: ['redis-server', '--appendonly', 'yes', '--loglevel', 'warning']
# command: ["redis-server", "--save", "60", "1", "--loglevel", "warning"] # uncomment if you want to use snapshotting instead of AOF
volumes:
- redis-data:/data

volumes:
postgres-data:
driver: local
driver_opts:
o: bind
type: none
device: ./.docker/database/postgresql/data

redis-data:
driver: local
driver_opts:
o: bind
type: none
device: ./.docker/database/redis

nodebb-build:
driver: local
driver_opts:
o: bind
type: none
device: ./.docker/build

nodebb-uploads:
driver: local
driver_opts:
o: bind
type: none
device: ./.docker/public/uploads

nodebb-config:
driver: local
driver_opts:
o: bind
type: none
device: ./.docker/config
51 changes: 51 additions & 0 deletions docker-compose-redis.yml
@@ -0,0 +1,51 @@
version: '3.8'

services:
nodebb:
build: .
# image: ghcr.io/nodebb/nodebb:latest
restart: unless-stopped
ports:
- '4567:4567' # comment this out if you don't want to expose NodeBB to the host, or change the first number to any port you want
volumes:
- nodebb-build:/usr/src/app/build
- nodebb-uploads:/usr/src/app/public/uploads
- nodebb-config:/opt/config
- ./install/docker/setup.json:/usr/src/app/setup.json

redis:
image: redis:7.2.3-alpine
restart: unless-stopped
command: ['redis-server', '--appendonly', 'yes', '--loglevel', 'warning']
# command: ["redis-server", "--save", "60", "1", "--loglevel", "warning"] # uncomment if you want to use snapshotting instead of AOF
volumes:
- redis-data:/data

volumes:
redis-data:
driver: local
driver_opts:
o: bind
type: none
device: ./.docker/database/redis

nodebb-build:
driver: local
driver_opts:
o: bind
type: none
device: ./.docker/build

nodebb-uploads:
driver: local
driver_opts:
o: bind
type: none
device: ./.docker/public/uploads

nodebb-config:
driver: local
driver_opts:
o: bind
type: none
device: ./.docker/config