在 Docker 容器中运行 Docker 在技术上是可行的,但通常不推荐。镜像的Docker Hub 描述docker
有很多文档,通读它很重要。除非绝对必要,否则我通常也不认为从容器内部访问 Docker 套接字是最佳实践,并且作为一般规则,您不应该尝试在单个映像中运行两个程序。我强烈考虑对您的更高级别问题采取其他方法:这既不是标准也不是简单的设置。
有两种方法可以访问 DinD 套接字。它通过 TCP-over-TLS 在端口 2376 上发布它,或者如果您在嵌套的 Docker 内运行容器,则用于绑定挂载的“主机系统”是 DinD 容器。
(但是等等:对 Docker 套接字的网络 HTTP 访问不是安全灾难吗?这里有两个缓解措施:因为它在主机 Docker 内部,所以有一层 NAT/防火墙,除非你发布它;虽然您可以使用它来获得不受限制的 root 访问权限,但它仅适用于嵌套的 DinD 容器及其内容。)
您应该做的第一件事是将 Dockerfile 重写为标准节点映像。它不应该扩展docker
映像,因为它不是 Docker 映像,而是节点应用程序映像。
FROM node:12
WORKDIR /app
COPY . .
RUN npm install
CMD node app.js
EXPOSE 4000
启动 DinD,作为一个单独的容器:
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
现在您可以在主机 Docker 上启动一个容器,并给它一个指向嵌套 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
或者,您可以在 DinD 设置中运行此容器。
# 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