Running Docker inside a Docker container is technically possible, but generally disrecommended. The Docker Hub description for the docker
image has a lot of documentation and it's important to read through it. I also wouldn't usually consider it a best practice to access the Docker socket from inside a container unless it's absolutely necessary, and as a general rule you shouldn't be trying to run two programs in a single image. I would strongly consider taking some other approach to your higher-level problem: this is neither a standard nor a straightforward setup.
There are two ways to access the DinD socket. It publishes it via TCP-over-TLS on port 2376, or if you run a container inside the nested Docker, "the host system" for purposes of bind mounts is the DinD container.
(But wait: isn't network HTTP access to the Docker socket a security disaster? There are two mitigations here: since it's inside the host Docker, there's a layer of NAT/firewall and you can't access that nested Docker socket unless you publish it; and while you can use it to get unrestricted root access, it's only over the nested DinD container and its contents.)
The first thing you should do is rewrite your Dockerfile to be a standard Node image. It should not extend the docker
image, because it's not a Docker image, it's a Node-application image.
FROM node:12
WORKDIR /app
COPY . .
RUN npm install
CMD node app.js
EXPOSE 4000
Start DinD, as a separate container:
mkdir certs
docker network create myapp
docker run \
--privileged \
--net myapp \
--name docker
-e DOCKER_TLS_CERTDIR=/certs \
-v $PWD/certs:/certs \
-d \
docker:dind
Now you can either start a container on the host Docker, and give it a pointer to the nested Docker
docker build -t myapp .
docker run
--net myapp \
--name myapp \
-e DOCKER_HOST=tcp://docker:2376 \
-e DOCKER_TLS_VERIFY=1 \
-e DOCKER_CERT_PATH=/certs \
-v $PWD/certs/client:/certs \
myapp
Or, you can run this container inside the DinD setup.
# Add to the `docker run ... docker:dind` startup
# -p 127.0.0.1:22376:2376
export DOCKER_HOST=tcp://localhost:22376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=$PWD/certs/client
# These run inside the DinD Docker
docker build -t myapp .
docker network create myapp-dind
docker run
--net myapp-dind \
--name myapp \
-v /var/run/docker.sock:/var/run/docker.sock \
myapp
# Return to the host Docker
unset DOCKER_HOST DOCKER_TLS_VERIFY DOCKER_CERT_PATH