acceder a un contenedor docker desde otro contenedor

92

Creé dos contenedores Docker basados ​​en dos imágenes diferentes. uno de db y otro para servidor web. ambos contenedores se ejecutan en mi mac osx.

Puedo acceder al contenedor db desde la máquina host y de la misma manera puedo acceder al servidor web desde la máquina host.

sin embargo, ¿cómo accedo a la conexión db desde el servidor web?

la forma en que comencé db container es

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

Empecé wls container como

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

Puedo acceder a la base de datos en el host conectándome a

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

Puedo acceder a wls en el host como

http://localhost:7001/console
Vik
fuente
Entonces, ¿tanto el contenedor web como el contenedor db están en la máquina host? Si es así, ¿qué versión de Docker estás usando? Porque las versiones anteriores de Docker tenían una forma de hacerlo, mientras que las versiones nuevas tienen una forma diferente. ¿También puedes usar docker-compose? Lo que lo hará más fácil, pero no quiero dar una respuesta usando un método que no puede usar.
Caperneoignis
esta respuesta puede ayudar, cómo acceder a localhost desde un contenedor en mac os
Chaojun Zhong
Para redes externas, esta solución funcionó para mí stackoverflow.com/a/38089080/1770571
Salma Gomaa

Respuestas:

51

La forma más fácil es usar --link, sin embargo, las versiones más nuevas de la ventana acoplable se están alejando de eso y, de hecho, ese interruptor se eliminará pronto.

El enlace a continuación también ofrece una buena forma de conectar dos contenedores. Puede omitir la parte de adjuntar, ya que es solo una forma útil de agregar elementos a las imágenes.

https://deis.com/blog/2016/connecting-docker-containers-1/

La parte que le interesa es la comunicación entre dos contenedores. La forma más sencilla es hacer referencia al contenedor de base de datos por el nombre del contenedor del servidor web.

Ejemplo:

nombró el contenedor db db1y el contenedor del servidor web web0. Ambos contenedores deben estar en la red puente, lo que significa que el contenedor web debería poder conectarse al contenedor de base de datos haciendo referencia a su nombre.

Entonces, si tiene un archivo de configuración web para su aplicación, entonces para el host de base de datos usará el nombre db1.

si está usando una versión anterior de Docker, entonces debería usar --link.

Ejemplo:

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

luego, cuando inicie la aplicación web. utilizar:

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

y la aplicación web se vinculará a la base de datos. Sin embargo, como dije, el interruptor --link se eliminará pronto.

En su lugar, usaría docker compose, que construirá una red para usted. Sin embargo; deberá descargar Docker compose para su sistema. https://docs.docker.com/compose/install/#prerequisites

una configuración de ejemplo es como esta:

el nombre del archivo es 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}"

esto nombrará a la red con un nombre genérico, no puedo recordar fácilmente cuál es ese nombre, a menos que use el interruptor --name.

ES DECIR docker-compose --name setup1 up base.yml

NOTA: si usa el modificador --name, deberá usarlo cada vez que llame a docker compose, de docker-compose --name setup1 downmodo que pueda tener más de una instancia de servidor web y db, y en este caso, para que docker compose sepa qué instancia desea ejecutar comandos contra; y también para que pueda tener más de uno ejecutándose a la vez. Excelente para CI / CD, si está ejecutando una prueba en paralelo en el mismo servidor.

Docker compose también tiene los mismos comandos que Docker, por lo que docker-compose --name setup1 exec webserver do_some_command

la mejor parte es que, si desea cambiar db o algo así para la prueba unitaria, puede incluir un archivo .yml adicional en el comando up y sobrescribirá cualquier elemento con nombres similares, lo considero una clave => reemplazo de valor .

Ejemplo:

db.yml

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

Luego llame docker-compose --name setup1 up base.yml db.yml

Esto sobrescribirá el archivo db. con una configuración diferente. Cuando necesite conectarse a estos servicios desde cada contenedor, use el nombre establecido en servicio, en este caso, webserver y db.

Creo que esta podría ser una configuración más útil en su caso. Dado que puede establecer todas las variables que necesita en los archivos yml y simplemente ejecutar el comando para docker compose cuando necesite que se inicien. Así que empieza y olvídate de la configuración.

NOTA: no utilicé el --portcomando, ya que exponer los puertos no es necesario para la comunicación contenedor-> contenedor. Solo es necesario si desea que el host se conecte al contenedor o la aplicación desde fuera del host. Si expone el puerto, entonces el puerto está abierto a todas las comunicaciones que permite el host. Así que exponer la web en el puerto 80 es lo mismo que iniciar un servidor web en el host físico y permitirá conexiones externas, si el host lo permite. Además, si desea ejecutar más de una aplicación web a la vez, por cualquier motivo, exponer el puerto 80 evitará que ejecute aplicaciones web adicionales si también intenta exponer en ese puerto. Por lo tanto, para CI / CD es mejor no exponer puertos en absoluto, y si usa Docker compose con el interruptor --name, todos los contenedores estarán en su propia red para que no colisionen. Así que prácticamente tendrás un contenedor de contenedores.

ACTUALIZACIÓN: Después de usar más las funciones y ver cómo otros lo han hecho para programas CICD como Jenkins. La red también es una solución viable.

Ejemplo:

docker network create test_network

El comando anterior creará una "red_prueba" que también puede adjuntar a otros contenedores. Lo cual se simplifica con el --networkoperador de interruptores.

Ejemplo:

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

Por supuesto, si tiene configuraciones de red proxy, aún debe pasarlas a los contenedores usando las instrucciones de cambio "-e" o "--env-file". Para que el contenedor pueda comunicarse con Internet. Docker dice que la configuración del proxy debería ser absorbida por el contenedor en las versiones más nuevas de Docker; sin embargo, todavía los paso como un acto de costumbre. Este es el reemplazo del interruptor "--link" que desaparecerá. Una vez que los contenedores están conectados a la red que creó, aún puede hacer referencia a esos contenedores desde otros contenedores usando el 'nombre' del contenedor. Según el ejemplo anterior, eso sería db1. Solo tiene que asegurarse de que todos los contenedores estén conectados a la misma red y esté listo para comenzar.

Para obtener un ejemplo detallado del uso de la red en una tubería cicd, puede consultar este enlace: https://git.in.moodle.com/integration/nightlyscripts/blob/master/runner/master/run.sh

Cuál es el script que se ejecuta en Jenkins para una gran prueba de integración para Moodle, pero la idea / ejemplo se puede usar en cualquier lugar. Espero que esto ayude a otros.

Caperneoignis
fuente
1
Si el primer enlace no funciona, puede usar este. linode.com/docs/applications/containers/…
Caperneoignis
1
Para Doing Docker componer o hacer red, ¿cómo haría referencia el servidor web a la base de datos? ¿Usaría el nombre del contenedor? Parece que en el segundo enlace es el caso: Entonces, si define una base de datos y una APLICACIÓN, la aplicación tendría que hacer referencia en este caso: psql -U {USER} -h database -p 5432 {DATABASE}desde dentro del contenedor si me bombardearon en él
Fallenreaper
1
@Fallenreaper si está en el contenedor y docker compuso, usaría el nombre, usado en "servicios:" si no le dio un nombre explícitamente. Entonces, en el ejemplo, usaría "webserver" si estuviera intentando conectarse desde el contenedor "db" en el shell. Mire el ejemplo de db.yml, usaría los nombres webserver y db. Lo siento por la demora, se desvió y olvidé el aviso.
Caperneoignis
50

Es fácil. Si tiene dos o más contenedores en ejecución, complete los siguientes pasos:

docker network create myNetwork
docker network connect myNetwork web1
docker network connect myNetwork web2

Ahora se conecta desde el contenedor web1 al contenedor web2 o al revés.

Utilice las direcciones IP de la red interna que puede encontrar ejecutando:

docker network inspect myNetwork

Tenga en cuenta que solo las direcciones IP internas y los puertos son accesibles a los contenedores conectados por el puente de red.

Entonces, por ejemplo, suponiendo que el contenedor web1 se inició con: docker run -p 80:8888 web1(lo que significa que su servidor se está ejecutando en el puerto 8888 internamente), y la inspección myNetworkmuestra que la IP de web1 es 172.0.0.2, puede conectarse desde web2 a web1 usando curl 172.0.0.2:8888).

MxWild
fuente
1
Hola, ¿y cómo me conecto de web1 a web2? por ip, nombre de host? donde conseguir esta informacion?
Henry Ávila
En el archivo docker-compose.yml, cree redes: myNetwork.
MxWild
14
@ HenryÁvila Solo usa el nombre del contenedor (p web1. Ej. ) Como nombre de host.
Pascal
Montones de gracias. ¡Funcionó perfectamente!
medina hace
19

Tendrá que acceder a db a través de la ip de la máquina host, o si desea acceder a él a través de localhost: 1521, ejecute el servidor web como -

docker run --net=host --name oracle-wls wls-image:latest

Mira aquí

xitter
fuente
1
¿Cómo funcionará esto en la vida real, ya que la ip del host cambiará según los contenedores de la máquina que se estén ejecutando?
Vik
1
Eso es válido solo si la máquina tiene IP estática o DNS; de lo contrario, siga el segundo enfoque.
xitter
Parece que tengo problemas con esto. mi comando de ejecución exacto es: docker run --name ora-tools-wls -it -p 7001: 7001 orawls esto funciona y me permite acceder a mi servidor que se ejecuta en este contenedor como localhost: 7001 / console Sin embargo, el acceso a la base de datos desde el servidor necesita ip exacta para llegar a otro contenedor que ejecuta la base de datos. Si voy con docker run --name ora-tools-wls -it -p 7001: 7001 --network = "host" orawls, entonces el servidor puede acceder a la base de datos con localhost como ip como mencionaste, pero accede al servidor en el navegador de la máquina host falla.
Vik
3
No es necesario definirlo -p 7001:7001, ya que todos los contenedores utilizan la propia pila de red del host.
xitter
@Vik, tuve el mismo problema y descubrí que no es compatible con mac. tal vez eso es lo que estás haciendo también. > El controlador de red del host solo funciona en hosts Linux y no es compatible con Docker Desktop para Mac, Docker Desktop para Windows o Docker EE para Windows Server. docs.docker.com/network/host
Brent Fisher
9

Al usar docker-compose, los servicios se exponen entre sí por nombre de forma predeterminada. Docs .
También puede especificar un alias como;

version: '2.1'
services:
  mongo:
    image: mongo:3.2.11
  redis:
    image: redis:3.2.10
  api:
    image: some-image
    depends_on:
      - mongo
      - solr
    links:
      - "mongo:mongo.openconceptlab.org"
      - "solr:solr.openconceptlab.org"
      - "some-service:some-alias"

Y luego acceda al servicio utilizando el alias especificado como nombre de host, por ejemplo, mongo.openconceptlab.orgpara mongoen este caso.

Karuhanga
fuente