Run NodeJs inside Docker-in-Docker container

Issue

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.

Solution

A Docker container only runs one process. Your image runs the Node application (its CMD runs 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

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published