Saturday, August 12, 2017

Practices for building a docker image

The first thing docker build does is to send build context to Docker daemon, if the build context is big, it can take a long time – so long that you doubt if it hangs. This blog shares some practices I am doing to speed up building a docker image.

Speed up Vagrant

if you are hosting vagrant VMs on Windows, accessing sync folder will be slow. There is a plugin that adds NSF to Windows, unfortunately, it doesn’t work for me: my McAfee blocks it.

There are some configurations that can speed up Vagrant:

config.vm.provider "virtualbox" do |v|
               v.memory =2048
               v.cpus = "2"
               # change the network card hardware for better performance
               v.customize ["modifyvm", :id, "--nictype1", "virtio" ]
               v.customize ["modifyvm", :id, "--nictype2", "virtio" ]

               # suggested fix for slow network performance
               # see
               v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
               v.customize ["modifyvm", :id, "--natdnsproxy1", "on"] 


Add .dockerignore in the build context, files defined in the file will be ignored by docker when sending build context to the docker daemon.

echo ./server/log > .dockerignore
echo ./server/tmp >> .dockerignore

Change files in a running container

After you spend a lot of time building the docker image, you may find that it doesn’t work out as you expected, perhaps some configuration files are not setup correctly, you change those files, and then you need to rebuild the image again, which is unbearable waste of time.

My approach is:
1)      Add a volume to the image, which will be used to hold files to be copied to the container
VOLUME ["/942-docker-volume"]
Build the image

2)      Run a container, in the run command, mount the volume, and switch the entrypoint command. In the replaced entrypoint command, copy files from the mounted volume to replace files in the container. 

sudo docker run -it --name pm942 -p 8080:8080  -v /942-docker-volume/home:/942-docker-volume/home --entrypoint /bin/sh pm942 -c "cp /942-docker-volume/home/*.conf /pm942/ && cp /942-docker-volume/home/bin/*.sh /pm942/bin/ && cd ./bin && ./"

Notice the --entrypoint parameter, whose value is “/bin/sh”. Also notice the argument to “/bin/sh” is placed at the end, after the image name pm942. This --entrypoint command copies files from the mounted volume and replace files accordingly inside the container.

Or you can ignore the argument, and thus log into the container to manipulate it:

sudo docker run -it --name pm942 -p 8080:8080  -v /942-docker-volume/home:/942-docker-volume/home --entrypoint /bin/sh pm942