Rocker is a tool developed by Grammarly that is offering additional functionalities to build Docker images.
The syntax of the Rockerfiles is a superset of Dockerfiles.
Rocker is useful for creating minimal Docker images as you can split the process in 2 steps, the first to build your project in a first container and the second to ship and run. In the following part of this post we will further explain and show how we can use Rocker to easily generate Docker images for Python projects.
In the first container, we will install all the tools to generate the Python wheels like a C compiler and all the development headers and libraries. The second container will only hold the installed wheels and dynamic libraries.
First step: The build requirements
If you are already familiar with Dockerfiles, then moving to Rockerfile is really straightforward. The first step is to create a file named Dockerfile at the root of your project.
You can see the full repository here.
FROM python:2.7-slim
The begining of each step is defined by the FROM lines.
ADD . /src
WORKDIR /src
This is pretty standard Dockerfile syntax where we copy the sources of the project into a subfolder of the image.
RUN apt-get update && apt-get install -y \
build-essential
We install the build-essential package to be able to build Python packages having C dependencies.
REQUIRE ["Version"]
RUN sed -ie s/\'0.0\'/\'{{ .Version }}\'/g setup.py
Rocker provides a templating functionality that we use to set the version number of our package. This can be really useful if you use a CI and want to use the build number as the version number.
Here is an excerpt of our setup.py
setup(
name='rockerdemo',
version='0.0',
...
)
To pass the value of Version you will use the -var parameter
$ rocker build -var Version=1.0
Rocker provides the -print parameter to visualize the Rockerfile after it has been templated.
RUN python setup.py bdist_wheel
RUN pip wheel .
RUN pip wheel setproctitle gunicorn json-logging-py
We build all the wheels that we will need: our main app, its dependencies and the dependencies that we will need to actually run the container like gunicorn.
EXPORT /src/wheelhouse
All the wheels are stored in /src/wheelhouse, so we EXPORT this folder to be able to IMPORT it in the next step.
Second step: The container that we will ship and run
FROM python:2.7-slim
IMPORT /wheelhouse
RUN pip install --no-index --find-links=file:///wheelhouse rockerdemo setproctitle gunicorn json-logging-py
RUN rm -rf /wheelhouse
We IMPORT the wheels, install them and remove the /wheelhouse folder.
COPY docker/logging.conf /logging.conf
COPY docker/gunicorn.conf /gunicorn.conf
EXPOSE 8000
ENTRYPOINT ["/usr/local/bin/gunicorn", '--name", "rockerdemo", "--config", "/gunicorn.conf", "--log-config", "/loggin\
g.conf", "-b", ":8000", "rockerdemo:app"]
This part is pretty standard Dockerfile syntax.
Building, tagging and pushing the container
PUSH sebest/rocker-with-python-project:{{ .Version }}
PUSH sebest/rocker-with-python-project:latest
This part will tag the build and optionaly push it to the Docker registry if you use the -push parameter
The final step is to actually build the image and push it:
$ rocker build -var Version=1.2 -push