Docker-in-Docker: Building Images inside a Running Container
Imagine you are heading Project X in your friend's start-up. Your team has 5 people and you sat up yesterday, night to build the application, and it's finally done and running within your docker container. Your teammates come to work today, and you want them to be able to run it too, but they seem to be running into all kinds of dependency problems. You're frustrated because this background work takes too much of your time, and the release is next week. What can you do?
You finally came up with a solution - docker-in-docker!
This is not the only situation where it helps; there are many other situations too, where you might need docker-in-docker; a few are:
- Testing: You can ensure everything works by testing your application and its dependencies within a container. Then, you can save the configuration as an image that can be used by other team members or even deployed to production.
- Running CI/CD tools like Jenkins.
Requirements:
- A running container with docker installed in it (Method-1)
- Access to host
docker.sock
(Method-2)- Attach a volume:
/var/run/docker.sock:/var/run/docker.sock
- Attach a volume:
Method-1 (Docker-in-Docker with Docker installed)
Step-1
Run the particular container and make sure it has docker installed. For the sake of simplicity, I am using the official Docker image here.
docker run -it --name build-container docker sh
Here,
t
allocates a ttyi
keeps it interactive
Step-2
Import your code. I am using this sample crypto price monitor react app for this post.
Source Code: https://github.com/thejungwon/docker-reactjs
git clone https://github.com/thejungwon/docker-reactjs
cd docker-reactjs
docker build -t docker-reactjs:latest .
Step-3
Once the image building finishes, you can export it as a tar file.
docker save docker-reactjs:latest > /tmp/docker-reactjs.tar
Step-4
Now exit out of the container and run the docker cp
command for copying the tar image file.
exit
docker cp build-container:/tmp/docker-reactjs.tar .
Step-5
Now import the image from the tar file using docker load
command.
docker load -i docker-reactjs.tar
After loading the image, you can run the container as usual.
docker run docker-reactjs:latest
Method-2 (Docker-in-Docker using Host's /var/run/docker.sock
)
Step-1
Make sure you can make requests to the socket. Run the following command in the host machine to check that.
curl --unix-socket /var/run/docker.sock http://localhost/version
Here, --unix-socket
helps you connect through the Unix domain socket (HTTP).
Step-2
To run docker inside docker attach the socket as a volume to the container. For example:
docker run -v /var/run/docker.sock:/var/run/docker.sock \
-ti docker
Here,
-v
represents volumet
allocates a ttyi
keeps it interactive
Now you can run docker commands inside the container which will run on the host machine.
Step-3
After running the previous command, you should be inside the container. Once inside, you can run docker commands which run on host machine.
docker run hello-world
Let's try it out with a custom image. Create a Dockerfile
with the following content in it.
FROM node:20-slim
LABEL maintainer="AmreshSinha <[email protected]>"
WORKDIR /usr/node
WORKDIR app
RUN pwd
# command executable and version
ENTRYPOINT ["node"]
Now build the app.
docker build -t test-image .
Conclusion
There are many more ways to go the docker-in-docker road other than the methods we discussed above. For example, dind or using another runtime like sysbox runtime for better security, etc.
We will discuss them in future posts. Till then... 👋