Docker images are a powerful thing. They can save you a lot of time when it comes to development environment setup. Docker images are specified by Dockerfiles. The good thing about Dockerfiles is that they aren't written in a funky fresh new language that only the hippest developers can understand. If you feel comfortable on your bash you will be in the inner circle. OK, to be honest a little knowledge about docker magic is required too ...
As the docker adaption is moving further at Fröhlich ∧ Frei headquarters we are constantly discovering room for workflow optimization. One thing we noticed was that our Dockerfiles became a little bit too complex and that we had some duplicate Dockerfile code in different projects.
Obviously it would be better to create a set of base images that have everything on board for one specific technology stack. This would allow us to maintain and improve a small set base images and to use a very minimalistic Child-Dockerfile per project that only adds project specific instructions.
Makes sense ...
The problem is that these base images have to live somewhere. We knew that docker can push images to Docker Hub, but we ignored this functionality for a while because we thought that we won't be able to maintain the images there. In the last weeks we had a second thought on that.
Today I want to show you how to create your own images on Docker Hub and how maintaining them is actually fun.
Automated Builds to the rescue
A thing that always felt problematic to us was that we had to build and push images to Docker Hub from our local machines. That didn't feel like the CI approach we are trying to embrace for application development.
Being able to push any local image to Docker Hub any time, overwriting the current latest version just felt wrong. I think we agree that everything used in serious development should be in version control. That's why the single point of truth for an image should be a software repository and since we are not doing anything super secret or fancy here, it should be a public one on Github. That way all changes will be traceable.
OK let's get going. I will walk you through the process of how to create your own Docker Hub image backed by a Github repository.
1. Create a Github repo containing your Dockerfile
In our case we created an image for static website development with jekyll. You can find the repository on Github at froehlichundfrei/jekyll-website. It is based on the official docker images for ruby 2.2 and node 0.12. Have a look at the Dockerfile and you will see that we simply combined the Dockerfiles of both images.
A little bit extra special hot sauce is also included:
- python-pygments, make, openjdk-7-jre (Unix Packages)
- jekyll, s3_website (Ruby gems)
- bower, gulp (Node modules)
Further you should include a README and a LICENCE file. That's all we need to create a Docker Hub repository.
2. Setup an automated build on Docker Hub
Now that the repository is existing, we have to set up the connection to Docker Hub. Actually this is not that hard.
Create a Docker Hub account
Link your Github account to the Docker Hub account
Go to Settings > Linked Accounts & Services > Link Github and link your account with the Public and Private option (otherwise you will not be able to access your organization repositories)
Setup an Automated Build for your Github repository.
Select Create > Create Automated Build and choose your repository.
Here you can specify which branch will be used for the Docker Hub image. In our case the master branch will trigger new builds on Docker Hub.
That was easy!
Now that our Docker Hub repository is linked to our Github repository we do not have to care about building and pushing images to Docker Hub anymore. When a new commit is pushed to the master branch of our Github repository Docker Hub will automatically build a new latest version of the docker image.
3. Where to go from here?
We can now use our froehlichundfrei/jekyll-website image to create a new jekyll based website. Every time we update the base image, all our projects using it will pull the latest version when they are built.
You are welcome to take our jekyll-website image for a ride and start your own instance of our blog. To do that just create a
Dockerfile with the following content:
FROM froehlichundfrei/jekyll-website:latest RUN git clone https://github.com/froehlichundfrei/froehlichundfrei.github.io.git /froehlichundfrei.github.io WORKDIR /froehlichundfrei.github.io RUN npm install CMD ["make", "serve"]
... and build and start the image locally:
# build the docker image # browser-sync takes some time to install ... docker build -t froehlichundfrei/froehlichundfrei.github.io . # run the image docker run -d -p 3000:3000 --volumes-from datadock \ --name froehlichundfrei.github.io -h froehlichundfrei.github.io \ froehlichundfrei/froehlichundfrei.github.io
You should now be able to access a local copy of our blog here:
What do you think?
There are people who say that public docker images aren't maintained enough and that this is a security issue. Our current approach for base images is to use the official docker images as a blueprint. Perhaps it is not the best approach, but we think it is a good starting point. If you have better ideas we would really like to discuss best practices with you guys.
Some stars on Github or Docker Hub would be very kind too and if you would like to suggest improvements to our jekyll-website image, feel free to create a PR on Github.
Thanks for reading!