Common docker-compose
recipes
Development
Key points for docker-compose
in development:
- Provide a database image
- Use
webpack-dev-server
for the client - Use
nodemon
for 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
app
folder should trigger hot reloading in the client services and changes to theserver
folder should triggernodemon
in 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}