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

feat: docker improvements #12031

Merged
merged 44 commits into from
Nov 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
bd8b2eb
use yarn and debian slim build
stevefan1999-personal Oct 1, 2020
40827fd
feat: update Dockerfile to use multistage builds
stevefan1999-personal Aug 19, 2021
5710dbb
Create main.yml
stevefan1999-personal Aug 19, 2021
06ab160
remove some useless things from docker context and assume yarn by def…
stevefan1999-personal Dec 19, 2021
1c7faf1
remove all dotfiles in docker context
stevefan1999 Feb 3, 2022
9a61d65
no need for extra build tools, complain to the module author if there…
stevefan1999 Feb 3, 2022
cf0678d
specify the config file location instead of creating it
stevefan1999 Feb 3, 2022
f8c6495
set explicit config path
stevefan1999 Feb 3, 2022
43f1592
fix docker-compose example to use the exposed volumes
stevefan1999-personal Jul 10, 2022
cb1e7f4
dockerfile: upgrade alpine to 3.16
stevefan1999-personal Jul 10, 2022
4a4c2e1
dockerignore: add more ignorable entries
stevefan1999-personal Jul 10, 2022
431716c
docker-compose: change the way the docker startup process works
stevefan1999-personal Jul 10, 2022
f3b9a53
install: pass config path to child process as well
stevefan1999-personal Jul 10, 2022
f1025a6
setup: move config file resolution up before setup
stevefan1999-personal Jul 10, 2022
df80664
docker-entrypoint: don't fix CONFIG_DIR location but fix default loca…
stevefan1999-personal Jul 10, 2022
a26926f
docker-entrypoint: handle missing config file logic
stevefan1999-personal Jul 10, 2022
0f95faf
README: add simple notice on how to use it
stevefan1999-personal Jul 10, 2022
3ae3205
add missing semicolons
stevefan1999-personal Jul 10, 2022
51db0e8
docker-compose: remove multi override, use one big profile instead
stevefan1999-personal Jul 10, 2022
8c7c8db
workflows: remove main.yml, add platforms to buildx matrix in docker.yml
stevefan1999-personal Jul 10, 2022
61ef6cb
workflows: set docker buildx to build for amd64 and arm64 only
stevefan1999-personal Jul 11, 2022
8e96c1e
docker-entrypoint: don't force build everytime before start
stevefan1999-personal Jul 13, 2022
86d6f9a
docker-entrypoint: implement init verb
stevefan1999-personal Jul 13, 2022
40fc8cd
README: mention caveat with MongoDB
stevefan1999-personal Jul 13, 2022
14981a0
README: add Docker section placeholder for doc migration
stevefan1999-personal Jul 13, 2022
9c0e2bd
docker-entrypoint: add SETUP variable support
stevefan1999-personal Jul 13, 2022
9cbf58f
docker-compose: add force flag to ln on setup
stevefan1999-personal Jul 26, 2022
2829427
docker-compose: fix permission issue; docker-compose: fast exit if st…
stevefan1999-personal Jul 26, 2022
021b4f1
fix: remove redundant FROM
stevefan1999-personal Aug 11, 2023
4172224
docs: remove docker stuff (in favour of docs entry, nodebb/docs#78) b…
julianlam Aug 14, 2023
c0aafa9
fix: correctly check if directory is writable
oplik0 Aug 23, 2023
28cf4f2
fix: ignore .docker directory
oplik0 Aug 23, 2023
373e26b
fix: multi-arch docker builds and chown performance
oplik0 Aug 23, 2023
4b14bd9
chore: bump database image versions
oplik0 Sep 23, 2023
552f19d
fix: move from alpine to slim image
oplik0 Sep 23, 2023
bbc1df1
fix: use omit=dev instead of only=prod
oplik0 Sep 23, 2023
6bd69ec
feat: move entrypoint to install directory
oplik0 Sep 23, 2023
f5d5d79
feat: initialize mongodb user
oplik0 Sep 23, 2023
80854e5
feat: use separate rebuild stage
oplik0 Sep 23, 2023
54bea3c
fix: disable eslint for mongodb script
oplik0 Sep 23, 2023
416e856
fix: remove node_modules bind mount
oplik0 Sep 23, 2023
a44187d
feat: prepopulate database defaults for installation
oplik0 Sep 23, 2023
40e806b
feat: enable persistence in redis container
oplik0 Sep 23, 2023
9d21da8
docs: add some comments to the compose file
oplik0 Sep 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.*
logs
test
node_modules
commitlint.config.js
nodebb.bat
renovate.json
*.yml
*.md
Dockerfile
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ logs/
.eslintrc
test/files
*.min.js
install/docker/
6 changes: 3 additions & 3 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ jobs:
- name: Build and push Docker images
uses: docker/build-push-action@v5
with:
cache-from: type=gha
cache-to: type=gha,mode=max
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/arm/v7
push: true
tags: ${{ steps.meta.outputs.tags }}
platforms: linux/amd64,linux/arm64,linux/arm/v7
cache-from: type=gha
cache-to: type=gha,mode=max
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,6 @@ package-lock.json
/package.json
*.mongodb
link-plugins.sh
test.sh
test.sh

.docker/
38 changes: 24 additions & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,39 @@ USER node

RUN npm install --omit=dev

FROM node:lts as rebuild

FROM node:lts
ARG BUILDPLATFORM
ARG TARGETPLATFORM

RUN mkdir -p /usr/src/build && \
chown -R node:node /usr/src/build

COPY --from=npm /usr/src/build /usr/src/build

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

FROM node:lts-slim as run

ARG NODE_ENV
ENV NODE_ENV=$NODE_ENV \
daemon=false \
silent=false

RUN mkdir -p /usr/src/app && \
chown -R node:node /usr/src/app
WORKDIR /usr/src/app

ARG NODE_ENV
ENV NODE_ENV $NODE_ENV
COPY --chown=node:node --from=rebuild /usr/src/build /usr/src/app

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

USER node
WORKDIR /usr/src/app

RUN npm rebuild && \
npm cache clean --force
USER node

COPY --chown=node:node . /usr/src/app

ENV NODE_ENV=production \
daemon=false \
silent=false

EXPOSE 4567

CMD test -n "${SETUP}" && ./nodebb setup || node ./nodebb build; node ./nodebb start
VOLUME ["/usr/src/app/node_modules", "/usr/src/app/build", "/usr/src/app/public/uploads", "/opt/config"]
ENTRYPOINT ["./install/docker/entrypoint.sh"]
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ NodeBB requires the following software to be installed:

## Installation

[Please refer to platform-specific installation documentation](https://docs.nodebb.org/installing/os)
[Please refer to platform-specific installation documentation](https://docs.nodebb.org/installing/os).
If installing via the cloud (or using Docker), [please see cloud-based installation documentation](https://docs.nodebb.org/installing/cloud/).

## Securing NodeBB

Expand All @@ -59,6 +60,7 @@ It is important to ensure that your NodeBB and database servers are secured. Bea
2. Use `iptables` to secure your server from unintended open ports. In Ubuntu, `ufw` provides a friendlier interface to working with `iptables`.
* e.g. If your NodeBB is proxied, no ports should be open except 80 (and possibly 22, for SSH access)


## Upgrading NodeBB

Detailed upgrade instructions are listed in [Upgrading NodeBB](https://docs.nodebb.org/configuring/upgrade/)
Expand Down
61 changes: 46 additions & 15 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,55 @@
version: '3.5'
version: '3.8'

services:
node:
nodebb:
build: .
restart: unless-stopped
depends_on:
- db
ports:
- "4567:4567/tcp" # comment this out if you don't want to expose NodeBB to the host, or change the first number to any port you want
# uncomment if you want to use another container as a reverse proxy
# expose:
# - 4567
volumes:
- ./.docker/build:/usr/src/app/build
- ./.docker/public/uploads:/usr/src/app/public/uploads
- ./.docker:/opt/config
- ./install/docker/setup.json:/usr/src/app/setup.json
mongo:
image: "mongo:6-jammy"
restart: unless-stopped
expose:
- 4567 # use a reverse proxy like Traefik

db:
image: mongo:bionic
- "27017"
environment:
MONGO_INITDB_ROOT_USERNAME: nodebb
MONGO_INITDB_ROOT_PASSWORD: nodebb
MONGO_INITDB_DATABASE: nodebb
volumes:
- ./.docker/database/mongo/config:/etc/mongo
- ./.docker/database/mongo/data:/data/db
- ./install/docker/mongodb-user-init.js:/docker-entrypoint-initdb.d/user-init.js
profiles:
- mongo
postgres:
image: postgres:16.0-alpine
restart: unless-stopped
expose:
- 27017
- "5432"
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
POSTGRES_USER: nodebb
POSTGRES_PASSWORD: nodebb
POSTGRES_DB: nodebb
volumes:
- mongo:/data/db

volumes:
mongo:
- ./.docker/database/postgresql/data:/var/lib/postgresql/data
profiles:
- postgres
redis:
image: redis:7.2.1-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
expose:
- "6379"
volumes:
- ./.docker/database/redis:/data
profiles:
- redis
46 changes: 46 additions & 0 deletions install/docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash

export CONFIG_DIR="${CONFIG_DIR:-/opt/config}"
export CONFIG=$CONFIG_DIR/config.json
export FORCE_BUILD_BEFORE_START="${FORCE_BUILD_BEFORE_START:-false}"

# Supported verbs: install (web install), setup (interactive CLI session). Default: web install
# TODO: constraint it using a hash set (or hash table)
export NODEBB_INIT_VERB="${NODEBB_INIT_VERB:-install}"
# Setup variable for backward compatibility, default: <empty>
export SETUP="${SETUP:-}"

mkdir -p $CONFIG_DIR

# if the folder is mounted as a volume this can fail, the check below is to ensure there is still write access
chmod -fR 760 $CONFIG_DIR 2> /dev/null

if [[ ! -w $CONFIG_DIR ]]; then
echo "panic: no write permission for $CONFIG_DIR"
exit 1
fi

[[ -f $CONFIG_DIR/package.json ]] || cp install/package.json $CONFIG_DIR/package.json
[[ -f $CONFIG_DIR/package-lock.json ]] || touch $CONFIG_DIR/package-lock.json

ln -fs $CONFIG_DIR/package.json package.json
ln -fs $CONFIG_DIR/package-lock.json package-lock.json

npm install --omit=dev

if [[ -n $SETUP ]]; then
echo "Setup environmental variable detected"
echo "Starting setup session"
./nodebb setup --config=$CONFIG
elif [ -f $CONFIG ]; then
echo "Config file exist at $CONFIG, assuming it is a valid config"
echo "Starting forum"
if [ "$FORCE_BUILD_BEFORE_START" = true ]; then
./nodebb build --config=$CONFIG
fi
./nodebb start --config=$CONFIG
else
echo "Config file not found at $CONFIG"
echo "Starting installation session"
./nodebb "${NODEBB_INIT_VERB}" --config=$CONFIG
fi
1 change: 1 addition & 0 deletions install/docker/mongodb-user-init.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions install/docker/setup.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"mongo": {
"host": "mongo",
"port": 27017,
"database": "nodebb",
"username": "nodebb",
"password": "nodebb"
},
"redis": {
"host": "redis",
"port": 6379,
"database": 0
},
"postgres": {
"host": "postgres",
"port": 5432,
"database": "nodebb",
"username": "nodebb",
"password": "nodebb"
}
}
2 changes: 2 additions & 0 deletions install/web.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ function install(req, res) {
const database = nconf.get('database') || req.body.database || 'mongo';
const setupEnvVars = {
...process.env,
CONFIG: nconf.get('config'),
NODEBB_CONFIG: nconf.get('config'),
NODEBB_URL: nconf.get('url') || req.body.url || (`${req.protocol}://${req.get('host')}`),
NODEBB_PORT: nconf.get('port') || 4567,
NODEBB_ADMIN_USERNAME: nconf.get('admin:username') || req.body['admin:username'],
Expand Down
9 changes: 6 additions & 3 deletions src/cli/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ async function setup(initConfig) {
console.log('Press enter to accept the default setting (shown in brackets).');

install.values = initConfig;
const data = await install.setup();
let configFile = paths.config;
if (nconf.get('config')) {
configFile = path.resolve(paths.baseDir, nconf.get('config'));
const config = nconf.any(['config', 'CONFIG']);
if (config) {
nconf.set('config', config);
configFile = path.resolve(paths.baseDir, config);
}

const data = await install.setup();

prestart.loadConfig(configFile);

if (!nconf.get('skip-build')) {
Expand Down
2 changes: 2 additions & 0 deletions src/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ function checkSetupFlagEnv() {
let setupVal = install.values;

const envConfMap = {
CONFIG: 'config',
NODEBB_CONFIG: 'config',
NODEBB_URL: 'url',
NODEBB_PORT: 'port',
NODEBB_ADMIN_USERNAME: 'admin:username',
Expand Down