在另一个容器中运行一个容器意味着在一个 Docker 容器中运行一个 Docker 引擎。这在 Docker-in-Docker 中被称为 dind,我强烈建议不要这样做。您可以在线搜索“dind”并发现为什么在大多数情况下这是一个坏主意,但由于它不是您问题的主要对象,我不会进一步扩展这个主题。
在同一个容器中同时运行 node.js 进程和 neo4j 进程
虽然大多数人会告诉您不要在 Docker 容器中运行多个进程,但没有什么能阻止您这样做。如果您想遵循此路径,请查看 Docker 文档网站上的 Using Supervisor with Docker 或 Phusion baseimage Docker 映像。
请注意,随着时间的推移,这种处理方式会使您的 Docker 映像越来越难以维护。
链接容器
如您所见,从长远来看,让 Docker 映像尽可能简单(即:在 Docker 容器中运行一个且仅一个应用程序)将使您的生活更轻松。
当两个容器在同一个 Docker 引擎上运行时,将容器链接在一起是微不足道的。这只是一个问题:
- 让你的 neo4j 容器 expose 服务监听的端口
- 使用
--link <neo4j container name>:<alias> 选项运行您的 node.js 容器
- 在 node.js 应用程序配置中,将 neo4j 主机设置为
<alias> 主机名,docker 将负责将该连接转发到它分配给 neo4j 容器的 IP
当您想在不同的主机上运行这两个容器时,事情会变得更加困难。
使用 Docker Compose,您必须使用 link: 键来定义您的链接
新的 Docker 网络功能
您还发现,未来将不再支持链接容器,而让多个 Docker 容器进行通信的新方法是创建一个虚拟网络并将这两个容器连接到该网络。
以下是如何继续:
docker network create mynet
docker run --detach --name myneo4j --net mynet neo4j
docker run --detach --name mynodejs --net mynet <your nodejs image>
然后,您的节点应用程序配置应使用 myneo4j 作为要连接的主机。
要告诉 Docker Compose 使用新的网络功能,您必须使用 --x-networking 选项。你也不会使用links: 键。
使用新的网络功能还意味着您将无法为数据库定义任何别名。因此,您必须使用 容器名称。请注意,除非您在 docker-compose.yml 文件中使用 container_name: 键,否则 Compose 将根据包含您的 docker-compose.yml 的目录创建容器名称文件,在 yml 文件中找到的服务名称和一个数字。
例如,以下 docker-compose.yml 文件,如果在名为“foo”的目录中,将创建两个名为 foo_web_1 和 foo_db_1 的容器:
web:
build: .
ports:
- "8000:8000"
db:
image: postgres
当以docker-compose --x-networking up 启动时,Web 应用配置应使用foo_db_1 作为数据库主机名。
如果你使用container_name:
web:
build: .
ports:
- "8000:8000"
db:
image: postgres
container_name: mydb
当以docker-compose --x-networking up 启动时,Web 应用配置应使用mydb 作为数据库主机名。
使用 Docker Compose 使用 nodeJS 和 neo4j 运行 Web 应用的示例
在这个例子中,我将展示如何从github project aseemk/node-neo4j-template dockerize 使用 nodejs 和 neo4j 的示例应用程序。
我假设您已经安装了 Docker 1.9.0+ 和 Docker Compose 1.5+。
本项目将使用 2 个 docker 容器,一个用于运行 neo4j 数据库,一个用于运行 nodeJS 网络应用。
Docker 化 Web 应用程序
我们需要构建一个 Docker 镜像,Docker compose 将从该镜像中运行一个容器。为此,我们将编写一个 Dockerfile。
创建一个名为Dockerfile(注意大写D)的文件,其内容如下:
FROM node
RUN git clone https://github.com/aseemk/node-neo4j-template.git
WORKDIR /node-neo4j-template
RUN npm install
# ugly 20s sleep to wait for neo4j to initialize
CMD sleep 20s && node app.js
这个 Dockerfile 描述了 Docker 引擎为我们的 Web 应用程序构建 docker 映像 必须遵循的步骤。这个 docker 镜像将:
对 nodeJS 代码的快速回顾表明,作者允许我们使用NEO4J_URL 环境变量将 URL 配置为connect to the neo4j database。
对 neo4j 数据库进行 Docker 化
人们已经为我们解决了这个问题。我们将使用 Docker Hub 上的official Docker image for neo4j。
快速回顾自述文件告诉我们使用NEO4J_AUTH 环境变量来更改neo4j 密码。并且将此变量设置为none 将一起禁用身份验证。
设置 Docker Compose
在与我们的 Dockerfile 所在目录相同的目录中,创建一个 docker-compose.yml 文件,其内容如下:
db:
container_name: my-neo4j-db
image: neo4j
environment:
NEO4J_AUTH: none
web:
build: .
environment:
NEO4J_URL: http://my-neo4j-db:7474
ports:
- 80:3000
此 Compose 配置文件描述了 2 个服务:db 和 web。
db 服务将从官方 neo4j docker 映像生成一个名为 my-neo4j-db 的容器,并将启动该容器,将 NEO4J_AUTH 环境变量设置为 none。
web 服务将使用 docker 镜像根据当前目录中的 Dockerfile 构建 (build: .) 生成一个以 docker compose 判断命名的容器。它将启动该容器,将环境变量NEO4J_URL 设置为http://my-neo4j-db:7474(注意我们在这里如何使用neo4j 容器的名称my-neo4j-db)。此外,docker compose 将指示 Docker 引擎在 docker 主机端口 80 上暴露 web 容器的端口 3000。
启动它
确保您位于包含 docker-compose.yml 文件的目录中并输入:docker-compose --x-networking up。
Docker compose 将读取 docker-compose.yml 文件,确定它必须首先为web 服务构建一个 docker 映像,然后创建并启动两个容器,最后将为您提供来自两个容器的日志。
一旦日志显示web_1 | Express server listening at: http://localhost:3000/,一切都已完成,您可以将您的互联网导航器指向http://<ip of the docker host>/。
要停止应用程序,请按 Ctrl+C。
如果您想在后台启动应用程序,请改用docker-compose --x-networking up -d。然后为了显示日志,运行docker-compose logs。
停止服务:docker-compose stop
删除容器:docker-compose rm
使 neo4j 存储持久化
官方 neo4j docker 镜像自述文件称容器将其数据保存在位于 /data 的卷上。然后我们需要指示 Docker Compose 将该卷挂载到 docker 主机上的目录中。
将 docker-compose.yml 文件更改为以下内容:
db:
container_name: my-neo4j-db
image: neo4j
environment:
NEO4J_AUTH: none
volumes:
- ./neo4j-data:/data
web:
build: .
environment:
NEO4J_URL: http://my-neo4j-db:7474
ports:
- 80:3000
使用该配置文件,当您运行 docker-compose --x-networking up 时,docker compose 将创建一个 neo4j-data 目录并将其挂载到容器中的位置 /data。
启动应用程序的第二个实例
创建一个新目录并复制Dockerfile 和docker-compose.yml 文件。
然后我们需要编辑 docker-compose.yml 文件以避免 neo4j 容器的名称冲突和 docker 主机上的端口冲突。
将其内容更改为:
db:
container_name: my-neo4j-db2
image: neo4j
environment:
NEO4J_AUTH: none
volumes:
- ./neo4j-data:/data
web:
build: .
environment:
NEO4J_URL: http://my-neo4j-db2:7474
ports:
- 81:3000
现在它已经为docker-compose --x-networking up 命令做好了准备。请注意,您必须在包含新 docker-compose.yml 文件的目录中才能启动第二个实例。