Suppeose I have a simple node.js app. I can build a container to run the app with a simple Dockerfile like this:
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y nodejs nodejs-legacy npm
COPY . /app
WORKDIR /app
RUN npm install
CMD node index.js
This will copy the source code into the container and I can ship it off to a registry no problem.
But for development I don't want to rebuild the container for every change in my code. So naturally, I use a volume in combination to nodemon. Here's my questions:
So my question is really: How do I keep dev and deploy environments separate. Two Dockerfiles? Two compose-files? Are there any best practices?
Docker Compose is an excellent tool for optimizing the process of creating development, testing, staging, and production environments.
Docker helps to ensure that all the developers have access to all the necessary bits and pieces of the software they work on. So if someone adds software dependencies, everyone has them when needed. If it is just one developer, there is no such need. But even in this case, Docker may help, eg.
So the way I handle it is I have 2 Docker files (Dockerfile
and Dockerfile.dev
).
In the Dockerfile.dev
I have:
FROM node:6
# Update the repository
RUN apt-get update
# useful tools if need to ssh in or used by other tools
RUN apt-get install -y curl net-tools jq
# app location
ENV ROOT /usr/src/app
COPY package.json /usr/src/app/
# copy over private npm repo access file
ADD .npmrc /usr/src/app/.npmrc
# set working directory
WORKDIR ${ROOT}
# install packages
RUN npm install
# copy all other files over
COPY . ${ROOT}
# start it up
CMD [ "npm", "run", "start" ]
# what port should I have
EXPOSE 3000
My NPM scripts look like this
"scripts": {
....
"start": "node_modules/.bin/supervisor -e js,json --watch './src/' --no-restart-on error ./index.js",
"start-production": "node index.js",
....
},
You will notice it uses supervisor for start so any changes to any file under src will cause it to restart the server without requiring a restart to docker.
Last is the docker compose.
dev:
build: .
dockerfile: Dockerfile.dev
volumes:
- "./src:/usr/src/app/src"
- "./node_modules:/usr/src/node_modules"
ports:
- "3000:3000"
prod:
build: .
dockerfile: Dockerfile
ports:
- "3000:3000"
So you see in a dev mode it loads and mounts the current directory's src
folder to the container at /usr/src/app/src
and also the node_modules
directory to the /usr/src/node_modules
.
This makes it so that I can make changes locally and save, the volume will update the container's file, then supervisor will see that change and restart the server.
** Note as it doesn't watch the node_modules folder you have to change another file in the src directory to do the restart **
Use environment variables. See the documentation Docker env. This is the recommended way, also for use in the production.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With