【问题标题】:How to link multiple Docker containers and encapsulate the result?如何链接多个 Docker 容器并封装结果?
【发布时间】:2017-11-10 02:57:19
【问题描述】:

我有一个连接到 Neo4j 数据库的 Node.js Web 应用程序。我想将这些封装在单个 Docker 映像中(也使用 Neo4j Docker container),但我是 docker 新手,似乎无法弄清楚这一点。在最新的 Docker 版本中推荐的方法是什么?

我的直觉是运行嵌套在应用容器内的 Neo4j 容器。但从我读过的内容来看,我认为支持/推荐的方法是将容器链接在一起。我需要的东西在this image 中有很好的说明。但是the article 我不清楚图像的来源。无论如何,它正在使用即将被弃用的legacy container linking,而现在推荐使用networking。教程或解释将不胜感激。

另外,docker-compose 如何融入这一切?

【问题讨论】:

    标签: docker encapsulation docker-networking


    【解决方案1】:

    在另一个容器中运行一个容器意味着在一个 Docker 容器中运行一个 Docker 引擎。这在 Docker-in-Docker 中被称为 dind,我强烈建议不要这样做。您可以在线搜索“dind”并发现为什么在大多数情况下这是一个坏主意,但由于它不是您问题的主要对象,我不会进一步扩展这个主题。

    在同一个容器中同时运行 node.js 进程和 neo4j 进程

    虽然大多数人会告诉您不要在 Docker 容器中运行多个进程,但没有什么能阻止您这样做。如果您想遵循此路径,请查看 Docker 文档网站上的 Using Supervisor with DockerPhusion 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_1foo_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 镜像将:

    • 基于official node docker image
    • Github克隆nodeJS示例项目
    • 将工作目录更改为包含 git clone 的目录
    • 运行npm install命令下载并安装nodeJS应用依赖
    • 指示 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 个服务:dbweb

    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://&lt;ip of the docker host&gt;/

    要停止应用程序,请按 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

    启动应用程序的第二个实例

    创建一个新目录并复制Dockerfiledocker-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 文件的目录中才能启动第二个实例。

    【讨论】:

    • 谢谢!这已经很有帮助了。但如果可能的话,我想澄清一些事情:[1] 如果你可以稍微增加最后一部分,假设读者对docker-compose 一无所知,那就太好了(这恰好是我的情况)。 [2] 您的最终配置能否用于启动同一设置的多个实例? (定义特定实例的参数将是暴露的 web-http-port、暴露的 neo4j-port 和暴露的 neo4j-directory,以使存储持久化。)
    • @mhelvens 工作量很大,但是自从我找到了一个使用 neo4j 的 nodeJS 项目后,我就可以搞定了。
    • 太棒了,谢谢! :-) 理想情况下,我想使用单行命令来启动新服务器,但如果 Docker 不能为我做到这一点,我可以编写一个 bash 脚本。
    • 哦,似乎 Neo4j 的卷需要(可以?)不再映射到任何本地目录以进行持久性。 docker 守护进程似乎有data-volumes 的集中存储。
    • 这是处理持久性的另一种方式。作品和我展示的作品都没有宣布将被弃用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-16
    • 2018-02-11
    • 2018-11-08
    • 2017-02-13
    相关资源
    最近更新 更多