Circus

If we reuse the Circus and Chaussette setup from Chapter 9, Packaging Runnerly, Circus can bind a socket on port 5000, and fork a few Flask processes, which will accept connection on that socket. Circus can also watch the single nginx process we want to run in our container.

The first step to using Circus as a process manager in our container is to install it, together with Chaussette, as follows:

RUN pip install circus chaussette 

From there, the following Circus configuration is similar to what we had in the previous chapter, except that we have one extra section for nginx:

[watcher:web] 
cmd = runnerly-tokendealer --fd $(circus.sockets.web)
use_sockets = True
numprocesses = 5
copy_env = True

[socket:web]
host = 0.0.0.0
port = 5000

[watcher:nginx]cmd = nginx -c /app/nginx.confnumprocesses = 1copy_env = True

The copy_env flag is used, so both Circus and the spawned processes have access to the container environment variables. That is why the configuration calls nginx directly without indicating its path since the PATH variable was set in our Dockerfile.

Once this INI file is created, it can be launched with the circusd command.

With all the previous changes, the finalized Dockerfile for our container looks like the following:

FROM python:3.6 

# OpenResty installation
RUN apt-get -y update &&
apt-get -y install libreadline-dev libncurses5-dev &&
apt-get -y install libpcre3-dev libssl-dev perl make
RUN curl -sSL https://openresty.org/download/openresty-1.11.2.3.tar.gz
| tar -xz &&
cd openresty-1.11.2.3 &&
./configure -j2 &&
make -j2 &&
make install
ENV PATH "/usr/local/openresty/bin:/usr/local/openresty/nginx/sbin:$PATH"

# config files
COPY docker/circus.ini /app/circus.ini
COPY docker/nginx.conf /app/nginx.conf
COPY docker/settings.ini /app/settings.ini
COPY docker/pubkey.pem /app/pubkey.pem
COPY docker/privkey.pem /app/privkey.pem

# copying the whole app directory
COPY . /app

# pip installs
RUN pip install circus chaussette
RUN pip install -r /app/requirements.txt
RUN pip install /app/

# logs directory
RUN mkdir /logs
VOLUME /logs

# exposing Nginx's socket
EXPOSE 8080

# command that runs when the container is executed

CMD circusd /app/circus.ini

In the Dockerfile example above, the SSH key are directly available in the repository to simplify the example for the book. In a real project, the production keys should be made available from outside the image through a mount point.

Assuming this Docker file is located in a /docker subdirectory in the microservice project, it can be built and then run with the following calls:

$ docker build -t runnerly/tokendealer -f docker/Dockerfile . 
$ docker run --rm --v /tmp/logs:/logs -p 8080:8080 --name tokendealer -it runnerly/tokendealer

The /logs mount point is mounted to a local /tmp/logs in this example, and the logs files are written in it.

The -i ;option makes sure that stopping the run with a Ctrl + C forwards the termination signal to Circus so that it shuts down everything properly. This option is useful when you run a Docker container in a console. If you do not use -i, and kill the run with Ctrl + ;C, the Docker image will still run, and you will need to terminate it manually via a docker terminate call.

The --rm option deletes the container when stopped, and the --name option gives a unique name to the container in the Docker environment.

Numerous tweaks can be added in this Dockerfile example. For instance, the sockets used by the Circus UIs (both web and command line) to control the Circus daemon could be exposed if you want to interact with it from outside the container.

You can also expose some of the running options, like the number of Flask processes you want to start--like environment variables--and pass them at run time via Docker with -e.

The fully working Dockerfile can be found at https://github.com/Runnerly/tokendealer/tree/master/docker.

In the next section, we will look at how containers can interact with each other.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset