I've been playing with docker a little bit now. And while is just playing and I don't have anything production ready, this are my insights on how docker containers should be provisioned/created.
You can have a single Dockerfile like this one:
# Based on the Ubuntu image FROM ubuntu # Bootstrap the node RUN apt-get update && aptitude -y safe-upgrade RUN sed -i 's/PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config # [...] # A lot of other RUN commands # [...] RUN cat /proc/mounts > /etc/mtab RUN mkdir -p /root/.ssh ADD authorized_keys /root/.ssh/authorized_keys RUN chmod 600 /root/.ssh/authorized_keys EXPOSE 22
To build a container you just run:
$ docker build -t superawesomeOS/featureX .
This is one possible approach. From my point of view you are scripting but in a very unconfortable way. And you will have problems very soon. Every time Docker runs a RUN command, a new container is created and executes the given command. Then it executes the next command but having as base the last generated container that now will have both changes. I like that, but is not perfect because you cannot create more that 42 aufs layers. Lets say that every aufs layer is a RUN/ADD execution.
What you should be doing instead of createing your script in a Dockerfile format is: create a regular bash script upload it to the server and then extract and execute it.
Lets create a script:
$ cat <<EOF > provision_container.sh apt-get update && aptitude -y safe-upgrade sed -i 's/PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config # [...] # A lot of other RUN commands # [...] cat /proc/mounts > /etc/mtab mkdir -p /root/.ssh cp /tmp/authorized_keys /root/.ssh/authorized_keys chmod 600 /root/.ssh/authorized_keys EOF
And our docker file would be something in the lines:
FROM ubuntu ADD provision_container.sh provision_container.sh ADD authorized_keys /tmp/authorized_keys RUN provision_container.sh EXPOSE 22
To build the container you just need to do:
$ ls ./ provision_container.sh Dockerfile authorized_keys $ docker build -t superawesomeOS/featureY .
We just need 3 actions (ADD/RUN) instead of a bunch of them. But still we have another drawback. We need to run as many ADD commands as files we want to upload and we have the limit of 42 aufs layers. On top of that with Dockerfile (and don't know why) does not allow absolute paths from the source file. From the documentation of Docker :
ADD <src> <dest> The ADD instruction will copy new files from <src> and add them to the container's filesystem at path <dest>. <src> must be the path to a file or directory relative to the source directory being built (also called the context of the build) or a remote file URL. <dest> is the absolute path to which the source will be copied inside the destination container. All new files and directories are created with mode 0755, uid and gid 0.
Not just don't allow absolute paths from the source, but it ignores the permissions of the file. The solution is exactly the same. Build a tar.gz with all your configurations and upload them to the server doing something like that:
# Generate a tar file like that: tar --append --file=config_files.tar /etc/resolv.conf /etc/hosts # If you can run this command again and the files will be appended: tar --append --file=config_files.tar /root/.ssh/authorized_keys # Create a zip (not required step) gzip config_files.tar
Now in our directory we should have:
:::code $ ls
config_files.tar.gz Dockerfile provision_container.sh
The Dockerfile would look like:
FROM ubuntu ADD provision_container.sh provision_container.sh ADD config_files.tar.gz config_files.tar.gz RUN tar zvxf config_files.tar.gz -D / RUN provision_container.sh EXPOSE 22
With this 4 lines (could be 3 if you untar from provision_container.sh) we are we are ready to go. The files have the original permissions, are deployed in the correct paths and we don't have the limit of 42 actions of a Dockerfile.
In fact, your Dockerfile now is more generic and you can with very little effort make an script that fills for you de FROM and EXPOSE tags and you can use this Dockerfile for all your projects, exactly the same way.