Docker in Docker actually makes a lot of sense, like the following scenario I encountered.
I need to use the CIDI service provided by the public cloud to trigger one-click build+test+deployment in the cloud, so I need an environment to build and release, but the build node in the cloud does not necessarily meet my criteria.
In the case of cloud build nodes we have no way to control (i.e. we can’t SSH directly to them).
It would be very comfortable to have a custom, stable Docker image that meets our requirements to serve as the environment for the entire CI/DI pipeline.
This is one of the goals of this article to achieve.
For example, I want the following environment.
- Have a Maven + JDK17 environment to package my source code.
- Have a Docker environment to push my packaged program as an image to a specified Docker product repository.
This environment is probably not available in the mainstream cloud CIDI anyway, mainly because JDK17 is too cutting edge. So let’s build a Docker image that has all of the above, well, that means we’re going to use Docker in Docker.
In fact, Alpine Linux’s Docker in Docker still has some pitfalls, the reason why I used this is also to make the image a little smaller. Fortunately, none of the problems are very big.
The commands and preparations provided below have been iterated several times and are complete. Other Alpine Linux Docker in Docker environments can also be changed based on this. So here is the official start of the display.
Your own environment should have Docker, because what we build is a Docker image specifically for building releases.
First confirm the Docker DNS, so that you don’t report an error when downloading software in Docker. alpine currently has this error.
Focus on the dns option below, make sure to set it.
Build the environment image (Dockerfile) we need
- apk update
- apk add docker
These commands are all necessary
The others are for adding libraries, source settings, and timezone calibration, so you can adjust them yourself. For example, if you want a git environment, just add an
apk add git to it.
The CMD startup command
dockerd is used to start the Docker daemon. If you do not add it, you will get the following error when using the docker command.
Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running?
Alpine Linux can’t use the systemctl command to start docker, it’s not that system.
The service library doesn’t exist either, so you can’t use our usual service docker start** command.
Execute the build command.
The docker-maven:jdk17 here can be replaced by yourself. Just as an example, the following is the same.
You need to give privileged permissions to run the container, otherwise it will report an error.
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: iptables failed: iptables -t nat -N DOCKER: iptables v1.8.7 (legacy): can’t initialize iptables table ’nat’: Permission denied (you must be root) Perhaps iptables or your kernel needs to be upgraded. (exit status 3)
The command to start is as follows.
Once you’re done booting, you can go in the container and have a blast!
Of course, I’m using this image as a build environment, so I don’t need to do anything in it, the actual build is automated in the cloud.
Then I just push it directly to the private repository and mount the environment directly in the pipeline console, adding a
-privileged=true startup parameter and it’s OK.
The overall result is very satisfactory.