Docker layers and updates

Programs installed in Docker

through Dockerfile are automatically seperated into layers per RUN command when images are being built.
There are usually three ways of building up your stack inside an Docker image:

  1. You can build on top of other image.
  2. You can issue your own command to install/configure programs from repositories or internet in your Dockerfile.
  3. You can have a script(or put this part directly in entrypoint.sh) run after the container start. Remember this is time consuming and shouldn’t involving anything that can potentially break your program. For example you wouldn’t want to upgrade your system dependency packages here. The benefit of doing so is every time the container start(or created from image, depending on how you implement it) your programs get installed all over again, keeping itself the latest version. This is the very kind of behavior some self updating OpenShift cartridge been performing. Heroku toolbelts do similar stuff as well. After each push of your repo, everything is built from scratch, to keep Ruby or Node.js, along with the packages your project needed latest version.

Updating Docker images

can be really easy since when composing it, your layers are built upon each other. Simply rebuild it from the Dockerfile then it will be up to date.

If your application use serveral images

you can simply update your images to the latest tagged version. This is always preferred procedure. If one of your components have official Docker image, don’t hesitate to do this way instead of composing your own image. Are you using basic services like Nginx Redis or PostgreSQL? Why not simply link them? Recreating containers from docker compose yaml file would be the fastest way to keep programs up to date.

Here is one real world example:

This blog is Dockerized, it is powered by Hexo which require Node.js to run.

  1. I decided to build from ubuntu 14.04 for one very simple reason: The official Node.js image is minimal configuration and will break my custom scripts and cron jobs. Besides I can always rebuild image with latest Node.js myself without spending too much time.
  2. I decided to install basic Hexo components within the Dockerfile as well as Node.js, since latest updates may not be capable with my current configuration. If included in image it will never change unless I build newer image to replace it.
  3. I linked Nginx to provide HTTPS reversed proxy.
  4. I write some scripts to install Hexo-hey, an admin interface for Hexo, and a few other plugins for Hexo. These scripts will run if container is newly created(No configuration file detected). Since these scripts always run itselves in a fresh container so all plugins will be up to date.

As you can see the updating difficulty is in descending order. I may recreate my containers any time then all Hexo plugins would be latest. I may pull latest images for Nginx then recreate my containers so Nginx would be latest. I’ll need to rebuild my Docker image and do manual push and pull if I want to update Hexo or Node.js to latest version, allowing me to test them before deploy to production server. I’ll need to manually edit Dockerfile to use another base image if I no longer love ubuntu 14.04.

Conclusion

Updating used to be painful. Docker made it very simple.