web-dev-qa-db-fra.com

Utilisation de l'ip de l'hôte dans docker-compose

Je veux créer un fichier docker-compose capable de s'exécuter sur différents serveurs.

Pour cela, je dois être capable de spécifier l'adresse IP ou le nom d'hôte du serveur (où tous les conteneurs s'exécutent) à plusieurs endroits dans le fichier de docker-compose.yml .

Par exemple. pour un conteneur consul où je veux définir comment le serveur peut être trouvé par les autres conteneurs consul.

consul:
  image: progrium/consul
  command: -server -advertise 192.168.1.125 -bootstrap

Je ne veux évidemment pas coder en 192.168.1.125.

Je pourrais utiliser env_file : pour spécifier le nom d'hôte ou l'adresse IP et l'adopter sur chaque serveur. J'ai donc cette information dans un placez et utilisez cela dans docker-compose.yml. Mais cela ne peut être utilisé que pour spécifier des variables d'environnement et non pour le paramètre advertise.

Y a-t-il une meilleure solution?

60
christian

docker-compose permet d'utiliser des variables d'environnement à partir de l'environnement exécutant la commande composer.

Voir la documentation sur https://docs.docker.com/compose/compose-file/#variable-substitution

En supposant que vous puissiez créer un script wrapper, comme suggéré par @balver, vous pouvez définir une variable d'environnement appelée EXTERNAL_IP Qui inclura la valeur de $(docker-machine ip).

Exemple:

#!/bin/sh
export EXTERNAL_IP=$(docker-machine ip)
exec docker-compose $@

et

# docker-compose.yml
version: "2"
services:
  consul:
    image: consul
    environment:
      - "EXTERNAL_IP=${EXTERNAL_IP}"
    command: agent -server -advertise ${EXTERNAL_IP} -bootstrap

Malheureusement, si vous utilisez une affectation de port aléatoire, il n'est pas possible d'ajouter EXTERNAL_PORT. Les ports doivent donc être liés de manière statique.

PS: Quelque chose de très similaire est activé par défaut dans HashiCorp Nomad, il inclut également les ports mappés. Doc: https://www.nomadproject.io/docs/jobspec/interpreted.html#interpreted_env_vars

17
Evgeny

Y a-t-il une meilleure solution?

Absolument! Vous n'avez pas du tout besoin de l'adresse IP de l'hôte pour la communication entre les conteneurs. Si vous link conteneurs dans votre docker-compose.yaml _, vous aurez accès à un certain nombre de variables d’environnement que vous pourrez utiliser pour découvrir les adresses IP de vos services.

Prenons, par exemple, une configuration de composition de menu fixe avec deux conteneurs: l'un utilisant consul et l'autre utilisant un service nécessitant une conversation avec consul.

consul:
  image: progrium/consul
  command: -server -bootstrap
webserver:
  image: larsks/mini-httpd
  links:
    - consul

Premièrement, en démarrant consul avec seulement -server -bootstrap, consul détermine sa propre adresse publicitaire, par exemple:

consul_1    | ==> Consul agent running!
consul_1    |          Node name: 'f39ba7ef38ef'
consul_1    |         Datacenter: 'dc1'
consul_1    |             Server: true (bootstrap: true)
consul_1    |        Client Addr: 0.0.0.0 (HTTP: 8500, HTTPS: -1, DNS: 53, RPC: 8400)
consul_1    |       Cluster Addr: 172.17.0.4 (LAN: 8301, WAN: 8302)
consul_1    |     Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false
consul_1    |              Atlas: <disabled>

Dans le conteneur webserver, nous trouvons les variables d'environnement suivantes disponibles pour le pid 1:

CONSUL_PORT=udp://172.17.0.4:53
CONSUL_PORT_8300_TCP_START=tcp://172.17.0.4:8300
CONSUL_PORT_8300_TCP_ADDR=172.17.0.4
CONSUL_PORT_8300_TCP_PROTO=tcp
CONSUL_PORT_8300_TCP_PORT_START=8300
CONSUL_PORT_8300_UDP_END=udp://172.17.0.4:8302
CONSUL_PORT_8300_UDP_PORT_END=8302
CONSUL_PORT_53_UDP=udp://172.17.0.4:53
CONSUL_PORT_53_UDP_ADDR=172.17.0.4
CONSUL_PORT_53_UDP_PORT=53
CONSUL_PORT_53_UDP_PROTO=udp
CONSUL_PORT_8300_TCP=tcp://172.17.0.4:8300
CONSUL_PORT_8300_TCP_PORT=8300
CONSUL_PORT_8301_TCP=tcp://172.17.0.4:8301
CONSUL_PORT_8301_TCP_ADDR=172.17.0.4
CONSUL_PORT_8301_TCP_PORT=8301
CONSUL_PORT_8301_TCP_PROTO=tcp
CONSUL_PORT_8301_UDP=udp://172.17.0.4:8301
CONSUL_PORT_8301_UDP_ADDR=172.17.0.4
CONSUL_PORT_8301_UDP_PORT=8301
CONSUL_PORT_8301_UDP_PROTO=udp
CONSUL_PORT_8302_TCP=tcp://172.17.0.4:8302
CONSUL_PORT_8302_TCP_ADDR=172.17.0.4
CONSUL_PORT_8302_TCP_PORT=8302
CONSUL_PORT_8302_TCP_PROTO=tcp
CONSUL_PORT_8302_UDP=udp://172.17.0.4:8302
CONSUL_PORT_8302_UDP_ADDR=172.17.0.4
CONSUL_PORT_8302_UDP_PORT=8302
CONSUL_PORT_8302_UDP_PROTO=udp
CONSUL_PORT_8400_TCP=tcp://172.17.0.4:8400
CONSUL_PORT_8400_TCP_ADDR=172.17.0.4
CONSUL_PORT_8400_TCP_PORT=8400
CONSUL_PORT_8400_TCP_PROTO=tcp
CONSUL_PORT_8500_TCP=tcp://172.17.0.4:8500
CONSUL_PORT_8500_TCP_ADDR=172.17.0.4
CONSUL_PORT_8500_TCP_PORT=8500
CONSUL_PORT_8500_TCP_PROTO=tcp

Il y a un ensemble de variables pour chaque port EXPOSEd par l'image consul. Par exemple, dans cette seconde image, nous pourrions interagir avec l'API consul REST en nous connectant à:

http://${CONSUL_PORT_8500_TCP_ADDR}:8500/
16
larsks

Avec la nouvelle version de Docker Compose ( 1.4. ), vous devriez pouvoir faire quelque chose comme ceci:

docker-compose.yml

consul:
  image: progrium/consul
  command: -server -advertise HOSTIP -bootstrap

bash

$ sed -e "s/HOSTIP/${HOSTIP}/g" docker-compose.yml | docker-compose --file - up

C'est grâce à la nouvelle fonctionnalité:

  • Compose peut maintenant lire la configuration YAML à partir d'une entrée standard, plutôt que d'un fichier, en spécifiant - en tant que nom de fichier. Cela facilite la génération dynamique de la configuration:

    $ echo 'redis: {"image": "redis"}' | docker-compose --file - up
    
13
balver

J'ai utilisé l'IP du réseau interne de docker qui semble être statique: 172.17.0.1

11
user3873619

Les variables d'environnement, comme suggéré dans la solution précédente, sont créées par Docker lorsque les conteneurs sont liés. Mais les vars env ne sont pas automatiquement mis à jour si le conteneur est redémarré. Il n'est donc pas recommandé d'utiliser des variables d'environnement en production.

Docker, en plus de créer les variables d'environnement, met également à jour les entrées de l'hôte dans le fichier/etc/hosts. En fait, la documentation de Docker recommande d’utiliser les entrées Host de etc/hosts au lieu des variables d’environnement.

Référence: https://docs.docker.com/userguide/dockerlinks/

Contrairement aux entrées de l'hôte dans le fichier/etc/hosts, les adresses IP stockées dans les variables d'environnement ne sont pas automatiquement mises à jour si le conteneur source est redémarré. Nous vous recommandons d'utiliser les entrées de l'hôte dans/etc/hosts pour résoudre l'adresse IP des conteneurs liés.

7
Anand