Working with Docker I found a Dockerfile structure that can be reused for different images so that I can have a uniform building enviroment. Beside this, I chose to do most of the work in a shell script running in the container; this has some advantages: you can leverage the full power of the shell and it keeps the total number of levels low. Remember that Docker can handle at most 127 layers while using the devicemapper, while AUFS can handle something near 42 layers.
Dockerfile structure
My Dockerfiles are divided into four main sections:
1) copy files;
2) run setup;
3) expose ports;
4) set the starting command.
Copy files
First copy all the necessary files into the container. If there are lots of files it's better to enclose them in a tgz archive to have only a few "COPY" commands. Remember that each command in a Dockerfile creates a new layer, so it's better to have as few as possible.
I use /home as a handy location to save temporary files to.
Run setup
The actual work is done by the setup.sh shell script that is run inside the container and that uses the files copied before.
Well, removing setup.sh isn't really necessary: you can leave it where it is.
The setup.sh script is a shell script, so it can do a lot of things, for example unpack the website.tgz archive in its final directory, or change the permissions of the start.sh script to make it executable, or install additional packages using yum or apt-get, and so on...
Expose ports
Usually the service you're putting into a container uses some ports to communicate with the external world, so in every Dockerfile there's a section exposing such ports.
Set the starting command
The starting command of my containers is always the start.sh script, so that also this part of the Dockerfile is always the same.
Conclusions
As you can see there are only two parts of the Dockerfile you need to change:
1) the files you have to copy;
2) the ports to be exposed.
Everything else remains the same. What can change deeply from image to image is the setup.sh and start.sh scripts.
Actually even my start.sh script doesn't change too much because I'm using Monit to manage processes, so the script looks like:
But this is another story: I wrote an article on the use of Monit in Docker.
Dockerfile structure
My Dockerfiles are divided into four main sections:
1) copy files;
2) run setup;
3) expose ports;
4) set the starting command.
Copy files
First copy all the necessary files into the container. If there are lots of files it's better to enclose them in a tgz archive to have only a few "COPY" commands. Remember that each command in a Dockerfile creates a new layer, so it's better to have as few as possible.
COPY ./website.tgz /home/ ADD ./start.sh /start.sh
I use /home as a handy location to save temporary files to.
Run setup
The actual work is done by the setup.sh shell script that is run inside the container and that uses the files copied before.
ADD ./setup.sh /setup.sh RUN /bin/bash /setup.sh
RUN rm -f /setup.sh
Well, removing setup.sh isn't really necessary: you can leave it where it is.
The setup.sh script is a shell script, so it can do a lot of things, for example unpack the website.tgz archive in its final directory, or change the permissions of the start.sh script to make it executable, or install additional packages using yum or apt-get, and so on...
yum -y -q install tar
[ -d /srv ] || mkdir -m 755 /srv
cd /srv
tar xzf /home/website.tgz
rm /home/website.tgz
chmod 755 /start.sh
Expose ports
Usually the service you're putting into a container uses some ports to communicate with the external world, so in every Dockerfile there's a section exposing such ports.
EXPOSE 8100
EXPOSE 8101
Set the starting command
The starting command of my containers is always the start.sh script, so that also this part of the Dockerfile is always the same.
CMD [ "/bin/bash", "/start.sh" ]
Conclusions
As you can see there are only two parts of the Dockerfile you need to change:
1) the files you have to copy;
2) the ports to be exposed.
Everything else remains the same. What can change deeply from image to image is the setup.sh and start.sh scripts.
Actually even my start.sh script doesn't change too much because I'm using Monit to manage processes, so the script looks like:
monit -l - -c /etc/monit.conf
But this is another story: I wrote an article on the use of Monit in Docker.
Comments
Post a Comment