Ever since I noticed that the application we prepared has expanded significantly, I have decided to find a completely new method for automation of the process of its launching. It was important for me to find a solution which would make it possible to activate new features in isolation.
Discovering a simpler method of process automation would be a significant improvement of my work as well as the work of my entire team. I thought “Why not use Docker?”
During the preparation stage, I created two setups: one for the front-end application, and the other for API. Below you can see a presentation of what I’ve learned during the development process.
The first problem
I want to have a cloned repository in the container, so I added an ssh key via the ADD command in Dockerfile:
And bam! The file is not found. Why?
Let’s assume that we have the following folder structure:
1 2 3 4 5 6 7
docker/ |-- stuff/ | |-- test.txt |-- Dockerfile server/ |-- data | |-- setup.yml
build in the
login-queue folder and you can only add files from the local folder and its local subfolders, e.g. stuff.
If you want to add the
server folder, you’ll receive a message: “unable to prepare context”
Ever wondered why the image takes so long to build? Maybe you didn’t use
.dockerignore, to ignore files which are not necessary in the image. The
.git folder should be removed automatically as well as any temporary files.
Order of commands in Dockerfile
Docker saves each line form Dockerfile and after building each line is saved as a layer. It is very important not to change the order of particular commands too often.
1 2 3 4 5 6 7 8 9 10 11 12
FROM ubuntu RUN apt-get install -y software-properties-common python RUN add-apt-repository ppa:chris-lea/node.js RUN echo "deb http://us.archive.ubuntu.com/ubuntu/ precise universe" >> /etc/apt/sources.list RUN apt-get update RUN apt-get install -y nodejs RUN apt-get install -y nodejs=0.6.12~dfsg1-1ubuntu1 RUN mkdir /var/www ADD app.js /var/www/app.js CMD ["/usr/bin/node", "/var/www/app.js"]
For example, if you change the last line in Dockerfile, all previous lines will be downloaded from the cache while the last line will be modified. When you replace line No. 4, then all lines starting from Line 4 to the end, will be modified. For this reason it is worth to place commands which will not change, at the beginning of the file.
Copying files to image
It’s worth considering what a given image will be used for. If you need it to launch a service once, just copy the code content directly to the image:
COPY . /workdir
Unfortunately, this makes it impossible to edit files and every time you want to edit your code, you’ll have to build the image again.
If you’re using MacOS and want to use the built image for development, you have to approach this matter in a slightly different way. If you will use volumes then you have to be prepared that this is an extremely slow solution (e.g. copying a file from the host to the container is done with the speed of 4.5 MB/s, while copying internally in the container with speed 10-20x higher). Luckily, as you can see at link, the problem has been known and its solution is the key issue for the team responsible for developing Docker for Mac.
How can you use Docker for development in this situation?
You can use it for external services, e.g. Redis/PSQL/Elasticsearch or use ready solutions, which offer rsync: https://github.com/brikis98/docker-osx-dev
To sum up
If you have a big team and wish to test a new feature, docker will be the ideal tool! Nevertheless, would I use it for a production launch of a server? I’m not fully convinced yet…
Additionally, I recommend a few outstanding articles:
- how to test images
- something else about Docker, but also worth mentioning
- last but not least, Docker documentation