we will use docker containers to manage the different services. Here is an example of a http server container and an api server container, that we will use as an example for two containers built to communicate with each other, open a port to the host and automate the start up including the build and shutdown processes.
what is docker anyway? Here is a list of basic commands to get started
1 2 3 4 5 6 7 8 9 10 11 12 13 |
docker pull ubuntu docker container ls -a docker ps docker ps -aq docker rm container docker rmi image docker images docker create --name nameit nginx docker attach nameit docker start nameit docker run -it --name nameit nginx docker run -d -p 8080:80 --name nameit2 -v nginx docker exec -it nameit2 bash |
For setting up our docker server container, using a http_server.Docker file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# this container is based on ubuntu:18.04 image FROM ubuntu:20.04 # run some commands as root to install needed packages RUN apt-get update -y RUN apt-get install -y nano RUN apt-get install -y python3.8 RUN apt-get install -y sudo # create user with temp pw, add him to group and delete tmp pw RUN useradd p_server_user -p 'temporary' -u 1001 -m RUN passwd -d p_server_user RUN usermod -aG sudo p_server_user # from here on we run commands as the user USER p_server_user # set some env variables WORKDIR /home/p_server_user/src ENV PORT=8888 # expose port to host EXPOSE 8888 |
now to automate the process of building and starting the server container with a shell script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#!/bin/bash docker build \ --file=http_server.Dockerfile \ --tag="http_server:0.1" \ . docker create \ --interactive \ --tty \ --rm \ --name=http_server\ --publish-all \ --mount type=bind,source="$(pwd)/src",target=/home/p_server_user/src \ --workdir /home/p_server_user/src \ server_container:0.1 docker start http_server docker port http_server docker attach http_server |
don’t forget to make it executable
1 2 |
sudo chmod +x server_builder.sh ./server_builder.sh |
Now we will make the same for the node.js api server that the http container will communicate with, this is the api_server.Dockerfile:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# this container is based on node:12.18-slim image FROM node:12.18-slim # run some commands as root to install needed packages RUN apt-get update -y RUN apt-get install -y nano RUN apt-get install -y sudo # add default container user to group and delete default pw RUN passwd -d node RUN usermod -aG sudo -u 1001 node # from here on we run commands as the user USER node # set some env variables WORKDIR /home/node/src # node container launches into nodejs env, we want it to start into shell, this forward this comman CMD ["/bin/bash"] ENV PORT=12345 # expose port to host EXPOSE 12345 |
then the deployment shell script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#!/bin/bash docker build \ --file=api_server.Dockerfile \ --tag="api_server:0.1" \ . docker create \ --interactive \ --tty \ --rm \ --name=api_server \ --publish-all \ --mount type=bind,source="$(pwd)/src",target=/home/node/src \ --workdir /home/node/src \ api_server:0.1 docker start api_server docker port api_server docker attach api_server |
We will create a simple express.js function on the api server as a backend for the http server. For that we will need to install express, and initiate npm with our service:
1 2 |
npm init # give it a name like api_server npm install express |
then let’s create our service, e.g. api_server.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#!/usr/local/bin/node var express = require('express'); var app = express(); app.listen(process.env.PORT); app.get( '/person', function (req, res) { res.json({ name: 'Tom', surname: 'Jerry' }) } ); |
Now we can let docker compose take care of handling the set up of these containers and especially the communication between them. For that we will create our composer config file docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
version: '3' services: api: image: api_server:0.1 container_name: api_server build: context: ./api_server dockerfile: api_server.Dockerfile command: /home/node/src/api_server.js volumes: - ./api_server/src:/home/node/src web: image: http_server:0.1 container_name: http_server build: context: ./http_server dockerfile: http_server.Dockerfile command: /home/http_server_user/src/http_server.py volumes: - ./http_server/src:/home/http_server_user/src ports: - 8080:8888 environment: - API_SERVER_URL=http://api:12345 |
once we run docker-compose, we will have the http server available on localhost:8080, the api server will not be reachable from outside the container, except for http server. Now let’s create the start.sh scripts:
1 2 3 4 |
#!/bin/bash docker-compose up -d --build docker port http_server |
and respectively the stop.sh script, don’t forget to make them executable!
1 2 |
#!/bin/bash docker-compose down |