在另一个容器中运行一个容器意味着在一个 Docker 容器中运行一个Docker 引擎。这被称为Docker-in-Docker 的dind,我强烈建议不要这样做。您可以在线搜索“dind”并发现为什么在大多数情况下这是一个坏主意,但由于它不是您问题的主要对象,我不会进一步扩展这个主题。
在同一个容器中同时运行 node.js 进程和 neo4j 进程
虽然大多数人会告诉你不要在 Docker 容器中运行多个进程,但没有什么能阻止你这样做。如果您想遵循此路径,请查看Docker 文档网站中的Using Supervisor with Docker ,或Phusion baseimage Docker 映像。
请注意,这种做事方式会使您的 Docker 映像随着时间的推移越来越难以维护。
链接容器
正如您所发现的,从长远来看,保持 Docker 映像尽可能简单(即:在 Docker 容器中运行一个且仅一个应用程序)将使您的生活更轻松。
当两个容器在同一个 Docker 引擎上运行时,将容器链接在一起是微不足道的。这只是一个问题:
- 让您的 neo4j 容器公开其服务侦听的端口
--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:
密钥。
使用新的网络功能还意味着您将无法为 db 定义任何别名。因此,您必须使用容器名称。请注意,除非您在docker-compose.ymlcontainer_name:
文件中使用密钥,否则Compose 将根据包含docker-compose.yml文件的目录、在 yml 文件中找到的服务名称和一个数字来创建容器名称。
例如,以下docker-compose.yml文件,如果在名为“foo”的目录中,将创建两个名为foo_web_1
and的容器foo_db_1
:
web:
build: .
ports:
- "8000:8000"
db:
image: postgres
以 开头时docker-compose --x-networking up
,Web 应用程序配置应用foo_db_1
作 db 主机名。
而如果你使用container_name
:
web:
build: .
ports:
- "8000:8000"
db:
image: postgres
container_name: mydb
以 开头时docker-compose --x-networking up
,Web 应用程序配置应用mydb
作 db 主机名。
使用 Docker Compose 运行使用 nodeJS 和 neo4j 的 Web 应用程序的示例
在此示例中,我将展示如何将使用 nodejs 和 neo4j的 github 项目 aseemk/node-neo4j-template中的示例应用程序 dockerize。
我假设您已经安装了Docker 1.9.0+ 和Docker Compose 1.5+。
该项目将使用 2 个 docker 容器,一个用于运行 neo4j 数据库,一个用于运行 nodeJS Web 应用程序。
将 Web 应用程序 Docker 化
我们需要构建一个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映像必须遵循的步骤。此泊坞窗图像将:
- 基于官方node docker镜像
- 从Github克隆 nodeJS 示例项目
- 将工作目录更改为包含 git clone 的目录
- 运行
npm install
命令以下载并安装 nodeJS 应用程序依赖项
- 指示 docker 在运行该映像的容器时使用哪个命令
对 nodeJS 代码的快速回顾表明,作者允许我们使用环境变量配置用于连接 neo4j 数据库的 URL。NEO4J_URL
对 neo4j 数据库进行 Docker 化
好吧,人们已经为我们解决了这个问题。我们将使用可在 Docker Hub 上找到的 neo4j 的官方 Docker 镜像。
快速查看自述文件告诉我们使用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
服务将生成一个以my-neo4j-db
官方neo4j docker映像命名的容器,并将启动该容器,并将NEO4J_AUTH
环境变量设置为none
.
该web
服务将使用从当前目录( build: .
) 中找到的 Dockerfile 构建的 docker 映像生成一个名为 docker compose 的容器。它将启动该容器,将环境变量设置NEO4J_URL
为http://my-neo4j-db:7474
(注意我们在这里如何使用 neo4j 容器的名称my-neo4j-db
)。此外,docker compose 将指示 Docker 引擎在 docker 主机端口上公开web
容器的端口。3000
80
开火
确保您位于包含docker-compose.yml文件的目录中并输入:docker-compose --x-networking up
。
Docker compose 将读取docker-compose.yml文件,确定它必须首先为web
服务构建一个 docker 映像,然后创建并启动两个容器,最后将为您提供来自两个容器的日志。
一旦日志显示web_1 | Express server listening at: http://localhost:3000/
,一切都已准备好,您可以将您的 Internet 导航器指向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
目录并将其挂载到容器的 location/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文件的目录中才能启动第二个实例。