I have a simple express.js server that, for some operations, needs to spawn some docker containers. I want to dockerize this NodeJs server using a Dockerfile, so that it will spawn docker containers inside a docker container.
My Dockerfile currently looks like this:
FROM docker:23.0.6-dind-alpine3.18 RUN apk update RUN apk add --no-cache nodejs RUN apk add --no-cache npm RUN apk add --no-cache iptables bash RUN apk add --no-cache --upgrade bash WORKDIR /usr/src/app COPY package*.json ./ RUN npm install --force --verbose COPY . . RUN npm run completeBuild EXPOSE 4000 CMD ["npm","start"]
I build it with:
docker build -t trydocker .
And I run it with:
docker run --privileged -it -p 4000:4000 -p 2375:2375 -p 2376:2376 trydocker
The server process gets spawned correctly and I can access my express server via localhost:4000.
But when I try to call
docker pull from inside the container I get an error that says that my docker daemon is not running.
Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?
Instead, if I remove the last directive
CMD ["npm","start"] from the Dockerfile, the docker daemon starts correctly, but my server is not online!
Is there a way to have both running?
I have looked at some related issues, like this one, but it did not help.
A Docker container only runs one process. Your image runs the Node application (its
npm start) but because of this it does not run the nested Docker daemon.
If you really need Docker-in-Docker (do you?) then you need to launch the nested Docker daemon as a sibling container. This Docker Compose setup could do it, for example:
version: '3.8' services: docker: image: docker:24-dind privileged: true environment: DOCKER_TLS_CERTDIR: /certs volumes: - docker-certs-ca:/certs/ca - docker-certs-client:/certs/client - docker-data:/var/lib/docker app: build: . environment: DOCKER_HOST: tcp://docker:2376 DOCKER_TLS_CERTDIR: /certs volumes: - docker-certs-client:/certs/client volumes: docker-certs-ca: docker-certs-client: docker-data:
The Docker Hub
docker image page has some more details on the settings.
Your application image itself doesn’t embed the Docker daemon and so it can use a more normal
node image base
FROM node:lts # exactly the last half of your existing Dockerfile WORKDIR /usr/src/app COPY package*.json ./ RUN npm install --force --verbose COPY . . RUN npm run completeBuild EXPOSE 4000 CMD ["npm","start"]
Using Docker-in-Docker is usually discouraged, since there are many complexities around which Docker daemon you’re actually using and the DinD container must run in privileged mode. With this same Dockerfile, you could remove the
docker container and associated volumes, and instead bind-mount the host’s
/var/lib/docker.sock socket file into the container on the same path, which would allow you to launch containers on the host’s Docker daemon.
Answered By – David Maze