A ExpressJS server into a Docker Container
- Learn Docker
- Being able to launch a ExpressJS server using docker.
- (extra) use a process manager to ensure the Node server "reliability"
- (extra 2) save logs in separated files and let docker host "consume them"
- Three different ways of running the server
- (using pm2 support) logs are being stored in a separated file, ready to be consumed
- (using docker) logs consumption thru docker volumes
$ yarn start
This will start the server which will be listening in the port defined at the env.PORT
variable (8000
by default).
$ yarn serve
This will start the server using pm2 using the configuration defined at ecosystem.config.js
.
pm2 is configured to capture all the output and error logs thrown by NodeJS and to store them in separated files.
- Get the image from
docker pull chmartinez35/docker-express-server:latest
- or build it using the repo and running
docker build --tag=<your-tag> .
- or build it using the repo and running
- Run the image:
$ docker run -d -p <port_you_want_to_use>:<port_at_Dockerfile|4000> <tag>
where <tag>
could be chmartinez35/docker-express-server
or the tag you used with the build
command
This will run the server within the container with pm2 support.
If you use the docker image to run the server, you could take advantage of the logs being generated by pm2.
If you use docker, logs will be generated INSIDE the container instance, not in your local machine (or host). If you want to share those logs with your machine, you need to share the volume:
$ docker run -p <port_you_want_to_use>:<port_at_Dockerfile> -v $(PWD):/server <container_name|tag_from_above>
(/server
is the folder name you put at the Dockerfile).
For instance, if you run that command at the same level as this README file, you'll get a new folder called logs
, which will have two files (check their names at ecosystem.config.js
) that will get updated with the pm2 logs.
The image contains everything inside this repo + the node_modules folder. I decided to do it like this for simplicity sake. In further scenarios I might want to create images differently.
In the command from above, 4000
is the port defined as a ENV
variable at the Dockerfile
. The port defined by the machine running the docker will take precedence so be aware of that.
Also, the ExpressJS server is using the port defined at the Dockerfile
to open the server connection.
To put it in other words:
- The
Dockerfile
exposes a port number so the world outside the container can access what's inside of it. - The
Dockerfile
hasPORT
variable that will be used by the ExpressJS server to open the connection- if that variable is not present, the ExpressJS will use the one declared at
index.js
.
- if that variable is not present, the ExpressJS will use the one declared at
- When executing the
docker
command, you could aport remapping
, meaning that the container will think you're using its exposed port as the published port but actually you're using another one.
If you want to see the list of processes running you'll have to go to the container and execute a pm2 list
.
Another way of doing it is by using docker exec
.
docker exec <CONTAINER_ID> "./node_modules/.bin/pm2 list" // OR
docker exec <CONTAINER_ID> yarn pm2 list // this is more of a hack to make the container's bash to look for pm2 inside the `.bin` folder
- Docker guides: https://docs.docker.com/get-started/
- pm2 log management: http://pm2.keymetrics.io/docs/usage/log-management/
- Docker logging with the "ELK stack": https://logz.io/blog/docker-logging/
- Good reading about Logstash and the "ELK stack": https://dzone.com/articles/logging-at-scale-with-nodejs