从另一个容器访问 docker 容器 [英] accessing a docker container from another container

查看:45
本文介绍了从另一个容器访问 docker 容器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我基于两个不同的图像创建了两个 docker 容器.一个 db 和另一个用于网络服务器.两个容器都在我的 mac osx 上运行.

我可以从主机访问数据库容器,同样的方式可以从主机访问网络服务器.

但是,如何从网络服务器访问数据库连接?

我启动db容器的方式是

docker run --name oracle-db -p 1521:1521 -p 5501:5500 oracle/database:12.1.0.2-ee

我启动了 wls 容器

docker run --name oracle-wls -p 7001:7001 wls-image:latest

我可以通过连接到主机上的数据库

sqlplus scott/welcome1@//localhost:1521/ORCLCDB

我可以访问主机上的 wls

http://localhost:7001/console

解决方案

最简单的方法是使用 --link,但是较新版本的 docker 正在远离这种方式,事实上该开关将很快被移除.

下面的链接也提供了一个很好的连接两个容器的方法.您可以跳过附加部分,因为这只是向图像添加项目的有用方法.

https://web.archive.org/web/20160310072132/https://deis.com/blog/2016/connecting-docker-containers-1/

您感兴趣的部分是两个容器之间的通信.最简单的方法是从 webserver 容器中通过名称引用 DB 容器.

示例:

您命名了数据库容器 db1 和网络服务器容器 web0.容器应该都在桥接网络上,这意味着 Web 容器应该能够通过引用它的名称连接到数据库容器.

因此,如果您的应用程序有网络配置文件,那么对于数据库主机,您将使用名称 db1.

如果您使用的是旧版本的 docker,那么您应该使用 --link.

示例:

第一步:docker run --name db1 oracle/database:12.1.0.2-ee

然后当您启动 Web 应用程序时.使用:

第2步:docker run --name web0 --link db1 webapp/webapp:3.0

并且网络应用程序将链接到数据库.但是,正如我所说的,--link 开关将很快被删除.

我会改用 docker compose,它会为你构建一个网络.然而;您需要为您的系统下载 docker compose.https://docs.docker.com/compose/install/#prerequisites>

示例设置如下:

文件名是base.yml

版本:2"服务:网络服务器:图片:moodlehq/moodle-php-apache:7.1取决于:- D b卷:- /var/www/html:/var/www/html";- /home/some_user/web/apache2_faildumps.conf:/etc/apache2/conf-enabled/apache2_faildumps.conf";环境:MOODLE_DOCKER_DBTYPE:pgsqlMOODLE_DOCKER_DBNAME:moodleMOODLE_DOCKER_DBUSER:moodleMOODLE_DOCKER_DBPASS:m@0dl3ing"HTTP_PROXY:${HTTP_PROXY}";HTTPS_PROXY:${HTTPS_PROXY}";NO_PROXY:${NO_PROXY}";D b:图片:postgres:9环境:POSTGRES_USER: 情绪POSTGRES_PASSWORD:m@0dl3ing"POSTGRES_DB:情绪HTTP_PROXY:${HTTP_PROXY}";HTTPS_PROXY:${HTTPS_PROXY}";NO_PROXY:${NO_PROXY}";

这会将网络命名为通用名称,除非您使用 --name 开关,否则我一时想不起来那个名称是什么.

IE docker-compose --name setup1 up base.yml

注意:如果你使用 --name 开关,你将需要在调用 docker compose 时使用它,所以 docker-compose --name setup1 down 这样你就可以拥有更多webserver 和 db 的一个实例,在这种情况下,docker compose 知道您要针对哪个实例运行命令;并且这样您就可以同时运行多个.非常适合 CI/CD,如果您在同一台服务器上并行运行测试.

Docker compose 也有与 docker 相同的命令,所以 docker-compose --name setup1 exec webserver do_some_command

最好的部分是,如果你想为单元测试更改数据库或类似的东西,你可以在 up 命令中包含一个额外的 .yml 文件,它会覆盖任何具有相似名称的项目,我认为它是一个键=>值替换.

示例:

db.yml

版本:2"服务:网络服务器:环境:MOODLE_DOCKER_DBTYPE:ociMOODLE_DOCKER_DBNAME:XED b:图片:moodlehq/moodle-db-oracle

然后调用docker-compose --name setup1 up base.yml db.yml

这将覆盖数据库.使用不同的设置.当需要从每个容器连接到这些服务时,您使用服务下设置的名称,在本例中为 webserver 和 db.

我认为在您的情况下,这实际上可能是一个更有用的设置.由于您可以在 yml 文件中设置您需要的所有变量,并且只需在需要启动它们时运行 docker compose 命令.所以更多地开始它并忘记它的设置.

注意:我没有使用 --port 命令,因为容器->容器通信不需要公开端口.仅当您希望主机从主机外部连接到容器或应用程序时才需要它.如果公开端口,则该端口对主机允许的所有通信开放.因此,在端口 80 上公开 web 与在物理主机上启动 web 服务器相同,并且如果主机允许,将允许外部连接.此外,如果您想一次运行多个 web 应用程序,无论出于何种原因,如果您也尝试在该端口上公开,则公开端口 80 将阻止您运行其他 web 应用程序.因此,对于 CI/CD,最好根本不公开端口,如果使用带有 --name 开关的 docker compose,所有容器都将在自己的网络上,因此它们不会发生冲突.所以你几乎会有一个容器的容器.

更新:在进一步使用功能并查看其他人如何为 Jenkins 等 CICD 程序完成后.网络也是一个可行的解决方案.

示例:

docker network 创建 test_network

上述命令将创建一个test_network"您也可以连接其他容器.使用 --network 开关操作符可以轻松实现这一点.

示例:

docker run --分离--name db1 --network test_network -e MYSQL_ROOT_PASSWORD=${DBPASS}";-e MYSQL_DATABASE=${DBNAME}";-e MYSQL_USER=${DBUSER}";-e MYSQL_PASSWORD=${DBPASS}";--tmpfs/var/lib/mysql:rw mysql:5

当然,如果您有代理网络设置,您仍然应该使用-e"将这些设置传递到容器中.或--env-file"开关语句.因此容器可以与互联网进行通信.Docker 表示代理设置应该由较新版本的 docker 中的容器吸收;然而,我仍然将它们作为一种习惯行为传递.这是--link"的替代品.正在消失的开关.一旦容器连接到您创建的网络,您仍然可以使用容器的名称"从其他容器中引用这些容器.根据上面的示例,将是 db1.您只需要确保所有容器都连接到同一个网络,就可以了.

在cicd管道中使用网络的详细示例,可以参考这个链接:https://git.in.moodle.com/integration/nightlyscripts/blob/master/runner/master/run.sh

哪个是在 Jenkins 中运行的脚本,用于对 Moodle 进行大量集成测试,但该想法/示例可以在任何地方使用.我希望这对其他人有帮助.

I created two docker containers based on two different images. One of db and another for webserver. Both containers are running on my mac osx.

I can access db container from host machine and same way can access webserver from host machine.

However, how do I access db connection from webserver?

The way I started db container is

docker run --name oracle-db -p 1521:1521 -p 5501:5500 oracle/database:12.1.0.2-ee

I started wls container as

docker run --name oracle-wls -p 7001:7001 wls-image:latest

I can access db on host by connecting to

sqlplus scott/welcome1@//localhost:1521/ORCLCDB

I can access wls on host as

http://localhost:7001/console

解决方案

Easiest way is to use --link, however the newer versions of docker are moving away from that and in fact that switch will be removed soon.

The link below offers a nice how too, on connecting two containers. You can skip the attach portion, since that is just a useful how to on adding items to images.

https://web.archive.org/web/20160310072132/https://deis.com/blog/2016/connecting-docker-containers-1/

The part you are interested in is the communication between two containers. The easiest way, is to refer to the DB container by name from the webserver container.

Example:

you named the db container db1 and the webserver container web0. The containers should both be on the bridge network, which means the web container should be able to connect to the DB container by referring to it's name.

So if you have a web config file for your app, then for DB host you will use the name db1.

if you are using an older version of docker, then you should use --link.

Example:

Step 1: docker run --name db1 oracle/database:12.1.0.2-ee

then when you start the web app. use:

Step 2: docker run --name web0 --link db1 webapp/webapp:3.0

and the web app will be linked to the DB. However, as I said the --link switch will be removed soon.

I'd use docker compose instead, which will build a network for you. However; you will need to download docker compose for your system. https://docs.docker.com/compose/install/#prerequisites

an example setup is like this:

file name is base.yml

version: "2"
services:
  webserver:
    image: moodlehq/moodle-php-apache:7.1
    depends_on:
      - db
    volumes:
      - "/var/www/html:/var/www/html"
      - "/home/some_user/web/apache2_faildumps.conf:/etc/apache2/conf-enabled/apache2_faildumps.conf"
    environment:
      MOODLE_DOCKER_DBTYPE: pgsql
      MOODLE_DOCKER_DBNAME: moodle
      MOODLE_DOCKER_DBUSER: moodle
      MOODLE_DOCKER_DBPASS: "m@0dl3ing"
      HTTP_PROXY: "${HTTP_PROXY}"
      HTTPS_PROXY: "${HTTPS_PROXY}"
      NO_PROXY: "${NO_PROXY}"
  db:
    image: postgres:9
    environment:
      POSTGRES_USER: moodle
      POSTGRES_PASSWORD: "m@0dl3ing"
      POSTGRES_DB: moodle
      HTTP_PROXY: "${HTTP_PROXY}"
      HTTPS_PROXY: "${HTTPS_PROXY}"
      NO_PROXY: "${NO_PROXY}"

this will name the network a generic name, I can't remember off the top of my head what that name is, unless you use the --name switch.

IE docker-compose --name setup1 up base.yml

NOTE: if you use the --name switch, you will need to use it when ever calling docker compose, so docker-compose --name setup1 down this is so you can have more then one instance of webserver and db, and in this case, so docker compose knows what instance you want to run commands against; and also so you can have more then one running at once. Great for CI/CD, if you are running test in parallel on the same server.

Docker compose also has the same commands as docker so docker-compose --name setup1 exec webserver do_some_command

best part is, if you want to change db's or something like that for unit test you can include an additional .yml file to the up command and it will overwrite any items with similar names, I think of it as a key=>value replacement.

Example:

db.yml

version: "2"
services:
  webserver:
    environment:
      MOODLE_DOCKER_DBTYPE: oci
      MOODLE_DOCKER_DBNAME: XE
  db:
    image: moodlehq/moodle-db-oracle

Then call docker-compose --name setup1 up base.yml db.yml

This will overwrite the db. with a different setup. When needing to connect to these services from each container, you use the name set under service, in this case, webserver and db.

I think this might actually be a more useful setup in your case. Since you can set all the variables you need in the yml files and just run the command for docker compose when you need them started. So a more start it and forget it setup.

NOTE: I did not use the --port command, since exposing the ports is not needed for container->container communication. It is needed only if you want the host to connect to the container, or application from outside of the host. If you expose the port, then the port is open to all communication that the host allows. So exposing web on port 80 is the same as starting a webserver on the physical host and will allow outside connections, if the host allows it. Also, if you are wanting to run more then one web app at once, for whatever reason, then exposing port 80 will prevent you from running additional webapps if you try exposing on that port as well. So, for CI/CD it is best to not expose ports at all, and if using docker compose with the --name switch, all containers will be on their own network so they wont collide. So you will pretty much have a container of containers.

UPDATE: After using features further and seeing how others have done it for CICD programs like Jenkins. Network is also a viable solution.

Example:

docker network create test_network

The above command will create a "test_network" which you can attach other containers too. Which is made easy with the --network switch operator.

Example:

docker run 
    --detach 
    --name db1 
    --network test_network 
    -e MYSQL_ROOT_PASSWORD="${DBPASS}" 
    -e MYSQL_DATABASE="${DBNAME}" 
    -e MYSQL_USER="${DBUSER}" 
    -e MYSQL_PASSWORD="${DBPASS}" 
    --tmpfs /var/lib/mysql:rw 
    mysql:5

Of course, if you have proxy network settings you should still pass those into the containers using the "-e" or "--env-file" switch statements. So the container can communicate with the internet. Docker says the proxy settings should be absorbed by the container in the newer versions of docker; however, I still pass them in as an act of habit. This is the replacement for the "--link" switch which is going away. Once the containers are attached to the network you created you can still refer to those containers from other containers using the 'name' of the container. Per the example above that would be db1. You just have to make sure all containers are connected to the same network, and you are good to go.

For a detailed example of using network in a cicd pipeline, you can refer to this link: https://git.in.moodle.com/integration/nightlyscripts/blob/master/runner/master/run.sh

Which is the script that is ran in Jenkins for a huge integration tests for Moodle, but the idea/example can be used anywhere. I hope this helps others.

这篇关于从另一个容器访问 docker 容器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆