Creating a Custom Docker Image
CircleCI starts with the config.yml but the base of your build begins with the Dockerfile.
If you are entirely new to Docker, please check out the official getting started guide:
What is a Dockerfile?
Docker builds images automatically based on the information presented to it in the Dockerfile. This defines the operating system you'll be running, install any software or dependencies required for your project, and execute commands in the shell automatically.
Because many of our users often need similar environments and tools, we have created a selection of maintained Dockerfiles suited best for projects on CircleCI with different languages available. You can view these "convenience" images here: https://hub.docker.com/r/circleci/
Why make a custom Dockerfile?
While you can use our images to install your own tools on top of them, this may not be the most efficient method for your use case.
- You may have a large selection of software that needs to be included that would best be served in the base Docker image rather than installed on CircleCI every time you run a build
- You have unique OS requirements that we simply do not have a convenience image (cimg) for at this time.
On that note, if you think we are missing something, let us know! https://circleci.com/ideas/
How to make a Dockerfile
This tool is an automated script for Linux and MacOS to generate Dockerfiles for use with CircleCI.
This script will prompt you for some popular options for operating systems, tools, databases, and more. When the script is complete, it will generate a CircleCI config.yml. Commit your project and follow it from your CircleCI dashboard to begin building.
The new project will build your newly created Dockerfile and automatically push your image to Dockerhub.
After the Docker image has been published the `test_image` job will begin, which will pull your newly created Docker image from Dockerhub
Code your own Dockerfile
Get more fine control by building your own Dockerfile.
Official Docs: https://docs.docker.com/engine/reference/builder
Start with an empty folder with whatever name you like, and enter it with cd
Inside your folder you need your Dockerfile, it's most common to name this as such.
And you can open this file up in your favorite text editor.
'FROM' is the first and most important command in your Dockerfile. This specifies the base image for your Docker build. This is most commonly a distro of Linux though other options exist. You can browse through DockerHub to find a suitable base image for your Dockerfile.
You can see every image shows the pull command which also shows you the image name
You can also find the available tags for that base image. Tags are generally different versions or variants of the base image. Without a tag, you will always pull the newest image, if you want to ensure your builds are consistent you should choose a tag as well.
When you have chosen your image and tag you may insert this into your 'FROM' line like so
Adding 'WORKDIR' will set the working directory inside of the container. This will be the target for any following commands and act somewhat as the 'root' folder.
Now that we have an operating system we can work with, let's feed it a script. (This is optional)
Let's stay we have a script called install.sh in our root directory with our Dockerfile. What we want to do is copy that script into our running Docker container.
So somewhere underneath the 'FROM' command, let's add 'COPY'. COPY takes two parameters, the first being the source and the second being the destination.
COPY install.sh .
If you established the 'WORKDIR' earlier, this should copy install.sh to /app/install.sh
You now have a base image but, this container doesn't really do much, though it would run.
RUN will allow us to execute commands in the shell so we can control the OS the same way we would locally.
'RUN' is extremely powerful and can do anything you would be able to do sitting in front of the terminal. This command above will execute /app/install.sh
Minimize layers and keep your image small
Best practices to follow when writing Dockerfiles: https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/
One of the best reasons to use CirlceCI's convenience images is because of the high probability that we will have layers from your image cached on the host, decreasing your spin-up time. But you may want a smaller image, or have another need not solved by our images.
It is in your best interest to limit the number of layers in your build and the total build size.
Each ADD, COPY, and RUN command adds an additional layer to your build. Make sure when possible to chain commands like so.
Run apt-get update && apt-get upgrade -y \
apt-get install -y nodejs npm
Or give multi-stage builds a try: https://docs.docker.com/engine/userguide/eng-image/multistage-build/#use-multi-stage-builds
Start with a small base image
Many base images out there still come with a host of tools that you may not need at all for the purposes of your project.
Build your image
On your local machine, enter the terminal and enter the following command while in your root directory for the project.
docker build -t IMAGENAME/TAG
This command will start the build of your image as well as name it. The TAG is optional.
Push to Dockerhub
There are many ways to deploy your Docker build to a repo, right now we are only going to discuss pushing your image to Dockerhub.
Login to Dockerhub.
docker login -u USERNAME -p PASSWORD< /code>
Once you have logged in you are ready to submit your build to Docker.
docker push IMAGENAME/TAG
You've Done It!
Your docker image will now be available on the Dockerhub on your profile