Common docker-compose recipes
Development
Key points for docker-compose in development:
- Provide a database image
- Use
webpack-dev-serverfor the client - Use
nodemonfor the server - Run the migrations on starting the server container
- Run seed scripts on starting the server container so that you save time (instead of creating new items through the UI)
- Provide default values for everything - you should be able to bring the app up with no environment variables
- Mount folders that include your code changes as volumes. eg. changes to the
appfolder should trigger hot reloading in the client services and changes to theserverfolder should triggernodemonin the server service
Common package.json for both client and server
Check the Dockerfile recipes for
what Dockerfile-development could look like. If all dependencies are within
the same package.json file, then we build an image with all the dependencies
and reuse it for both the client and the server.
# docker-compose.yml
version: "3"
services:
client:
build:
context: .
dockerfile: ./Dockerfile-development
command: ["node_modules/.bin/coko-client-dev"]
ports:
- ${CLIENT_PORT:-4000}:${CLIENT_PORT:-4000}
environment:
- NODE_ENV=development
- CLIENT_PORT=${CLIENT_PORT:-4000}
- SERVER_PROTOCOL=http
- SERVER_HOST=localhost
- SERVER_PORT=${SERVER_PORT:-3OOO}
volumes:
- ./app:/home/node/app/app
server:
build:
context: .
dockerfile: ./Dockerfile-development
depends_on:
- db
entrypoint:
[
"node_modules/.bin/wait-for-it",
"db:5432",
"--",
"sh",
"scripts/docker/setupDevServer.sh",
]
command:
[
"node_modules/.bin/nodemon",
"startServer.js",
"--watch",
"server",
"--watch",
"config",
"--ext",
"js,graphql",
]
ports:
- ${SERVER_PORT:-3000}:${SERVER_PORT:-3000}
environment:
- NODE_ENV=development
- POSTGRES_HOST=db
- POSTGRES_PORT=5432
- POSTGRES_DB=${POSTGRES_DB:-pg_db}
- POSTGRES_USER=${POSTGRES_USER:-pg_user}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-pg_pass}
- PUBSWEET_SECRET=${PUBSWEET_SECRET:-ps_secret}
- SERVER_PORT=${SERVER_PORT:-3000}
- CLIENT_PROTOCOL=${CLIENT_PROTOCOL:-http}
- CLIENT_HOST=${CLIENT_HOST:-0.0.0.0}
- CLIENT_PORT=${CLIENT_PORT:-4000}
volumes:
- ./config:/home/node/app/config
- ./server:/home/node/app/server
db:
image: postgres:10-alpine
ports:
- ${POSTGRES_PORT:-5432}:5432
environment:
- POSTGRES_DB=${POSTGRES_NAME:-pg_db}
- POSTGRES_USER=${POSTGRES_USER:-pg_user}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-pg_pass}
Your entrypoint script for the server service could look something like this:
#!/bin/sh
set -x
# This is run through docker. Its CWD will be the root folder.
node_modules/.bin/pubsweet migrate
node scripts/setupAdminUser.js
node scripts/seedUsers.js
node scripts/seedManuscripts.js
exec "$@"
Production
Key points:
- Serve a static bundle of the client with an image like
nginx(see related Dockerfile recipe) - Do not provide default values for variables
- Do not provide a database at all. It is up to the sysadmin to provide the environment variables to connect to a working db. (eg. self-hosted, a db deployment on AWS etc)
# docker-compose.production.yml
version: "3"
services:
client:
build:
context: .
dockerfile: ./Dockerfile-production-client
args:
- server_protocol=${SERVER_PROTOCOL}
- server_host=${SERVER_HOST}
- server_port=${SERVER_PORT}
ports:
- ${CLIENT_PORT}:80
server:
build:
context: .
dockerfile: ./Dockerfile-production-server
ports:
- ${SERVER_PORT}:${SERVER_PORT}
environment:
- NODE_ENV=production
- POSTGRES_HOST=${POSTGRES_HOST}
- POSTGRES_PORT=${POSTGRES_PORT}
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- PUBSWEET_SECRET=${PUBSWEET_SECRET}
- SERVER_PORT=${SERVER_PORT}
- CLIENT_PROTOCOL=${CLIENT_PROTOCOL}
- CLIENT_HOST=${CLIENT_HOST}
- CLIENT_PORT=${CLIENT_PORT}