The development of such a project as
kubish.ru implies the use of various services that are not typical for an ordinary laptop, even if it is a developer’s laptop. Postgresql, Redis, Celery and so on. The desire to create a comfortable development and testing environment has led us to the need to use some kind of virtualization / isolation system. As an option, Vagrant was used for some time, but this is still ovrerhead and our search for the best way led, at the moment, to Docker.
Docker is a platform for running applications in isolated containers. Using containers in Linux allows software to be isolated from the base system. Unlike Virtualbox, system overheads necessary for hardware virtualization are excluded. Docker can help develop and deploy web applications and services. Let's see how this happens.
Why do I need a docker?
Docker can be used in various ways. It can provide services in the background, for example, PostgreSQL of a given version. A dockerizing application can be placed in a docker and in this way we can use images of such containers to deploy our application to production.
')
For python developers, Docker can be described as a virtualenv for any application. It can be either a Python interpreter or some other server. This is very convenient when you want to test new versions or want to run outdated applications on your server.
Docker installation
Docker is available in repositories in various Linux distributions. OSX and MS Windows users can use VirtualBox, on which the Linux system is installed, in order to run Docker.
To install the latest version I use
PPA for Ubuntu. When Docker is installed, you can add yourself to the “docker” group so that you don’t need to use sudo in the future.
First containers
When the Docker is ready, we can run a lot of containers from
registry.hub.docker.com , for example, Python. To run this container, simply run:
docker run -it --rm python:3.4
For starters, a running Docker will download several files. When the process is complete, we get the default console of the Python interpreter. The
-it command runs the container interactively and binds it to the console for interaction.
--rm will delete the current container after exiting. “Python” is the name of the source for the container. After the “:” we see a tag that usually shows the version — in this case, the Python version in the container.
We can also change the standard behavior of the container, for example, run our own script. To use the command from the command line, simply add the following:
docker run -it --rm python:3.4 ls
When our container is launched, the “ls” command will start inside it, which will show all the files and filters in the main directory.
Dockerfile
The
Dockerfile file contains the “cooking recipe” of our container. If we want to run a Python script, here’s what we need to write:
FROM python:3.4 ADD ./test.py / RUN ls -al CMD python test.py
FROM points to the base container, in this case the Python 3.4 image. Then we can use the
ADD , RUN, ENV commands to configure the container.
The RUN command will perform tasks when the container is built. The
CMD command will run at the beginning of the container start. The image building operations are cached and skip the next versions (the RUN command from the example starts the first build, but not the second build).
In the terminal we can write the following:
docker build --tag=foo . docker run -it --rm foo
Dockerfile on Django
django-ckeditor contains a demo application that can be launched through
manage.py and runserver. Let's try to make a dockfile that will create an image of this application:
FROM python:3.4 MAINTAINER Piotr Maliński <riklaunim@gmail.com> ADD . /ckeditor ENV DJANGO_SETTINGS_MODULE ckeditor_demo.settings RUN pip install -r /ckeditor/ckeditor_demo_requirements.txt RUN pip install /ckeditor RUN python /ckeditor/manage.py validate RUN python /ckeditor/manage.py collectstatic --noinput CMD python /ckeditor/manage.py runserver 0.0.0.0:8080
I use here Python 3.4. All code from the repository will be added to the “ckeditor” folder of the container. I also set the DJANGO_SETTINGS_MODULE environment variable, add dependencies and the editor itself. Further validation, static collection and at the end of the CMD to start the server. It is also convenient to make the server available outside the container, for this we run it on 0.0.0.0 IP
dockebuild --tag=django-ckeditor . dockerun -it --rm --publish=192.168.0.110:8080:8080 django-ckeditor
The
--publish option allows
you to map (mapping) the public IP / Port address from a running local container to a local one. In this example, 192.168.0.110 is the port of the host. The public port can be accessed through 8080 from my localhost. Without the publish option, the server will be accessible only from the running IP address of the container.
The configuration of Dockerfile, which I showed is not perfect and will only work with SQLite database. Docker allows you to run different services in different containers. For example, let's try, use the PostgreSQL database in the second container.
So let's run an instance of PostgreSQL:
docker run -d postgres:9.4
The Konetiner will start in the background and we can check its status and name with the
docker ps command . Default names are random, for example “clever_ptolemy”. We have now created a database on this server, but first we need an IP address. We can get it from
docker inspect INSTANCE_NAME , which will show a list of variables in the container, including the IP address. Next we can create a database:
createdb -h IP_ADDRESS DATABASE_NAME -U postgres
The database has been created and now we can configure it in the application container. Docker allows you to do this using environment variables. For Django, you can use
dj_database_url :
from os import environ
import dj_database_url DATABASES = {'default': dj_database_url.parse(environ.get('DATABASE', 'postgres:///'))}
Now we have to transfer the env variable with the database name to the container to make it work. It can be done like this:
docker run -it --rm --link=POSTGRES_INSTANCE_NAME:OUR_NAME -e DATABASE=postgres://postgres@OUR_NAME/DATABASE_NAME --publish=192.168.0.110:8080:8080 django-ckeditor
We can get the database instance name by running the “docker ps” command in the console. “OUR_NAME” is a label that we can use later in the -e value. In my case, it looked like this:
docker run -it --rm --link=clever_ptolemy:db -e DATABASE=postgres://postgres@db/ckeditor --publish=192.168.0.110:8080:8080 django-ckeditor python /ckeditor/manage.py syncdb docker run -it --rm --link=clever_ptolemy:db -e DATABASE=postgres://postgres@db/ckeditor --publish=192.168.0.110:8080:8080 django-ckeditor
The syncdb command is executed first, it will create tables in the database. Next, start the development server.
Tool Fig
The above simple example requires a lot of names and links. In order to make the process easier, there are several tools like fig. In the YAML (fig.yml) file, we can specify all the steps and links that are needed:
ckeditor: build: . command: python /ckeditor/manage.py runserver 0.0.0.0:8080 links: - db ports: - "8080:8080" db: image: postgres:9.4
Next, we can build the
fig build command and run c
fig up , which will show the operation of the application. We have several labels and we can run syncdb and use
fig run NAME COMMAND for help, where Name is the instance name of fig.yml. When fig is launched, you can check the list of containers with “docker ps”
You can read more about
fig.yml syntax on the application page. There is also a
Django tutorial in which another way to configure Postgres is provided.