Docker容器的本地主机名

enyaitl3  于 2023-03-07  发布在  Docker
关注(0)|答案(5)|浏览(159)

初级 Docker 的问题,
我有一个运行模块化应用程序的开发环境,它使用Docker Compose运行3个容器:服务器、客户端、数据库。
docker-compose.yml看起来像这样:

#############################
# Server
#############################
server:
  container_name: server
  domainname: server.dev
  hostname: server
  build: ./server
  working_dir: /app
  ports:
    - "3000:3000"
  volumes:
    - ./server:/app
  links:
    - database

#############################
# Client
#############################
client:
  container_name: client
  domainname: client.dev
  hostname: client
  image: php:5.6-apache
  ports:
     - "80:80"
  volumes:
   - ./client:/var/www/html

#############################
# Database
#############################
database:
  container_name: database
  domainname: database.dev
  hostname: database
  image: postgres:9.4
  restart: always
  environment:
    - POSTGRES_USER=postgres
    - POSTGRES_PASSWORD=root
    - POSTGRES_DB=dbdev
    - PG_TRUST_LOCALNET=true
  ports:
    - "5432:5432"
  volumes:
    - ./database/scripts:/docker-entrypoint-initdb.d # init scripts

您可以看到,我为每台计算机分配了一个. dev域名,这可以很好地从另一台计算机(Docker内部网络)查看一台计算机,例如,我在这里从client.dev的CLI ping server.dev

root@client:/var/www/html# ping server.dev
    PING server.dev (127.0.53.53): 56 data bytes
    64 bytes from 127.0.53.53: icmp_seq=0 ttl=64 time=0.036 ms
    • 这在内部运行良好,但在我的主机操作系统网络上无法运行。**

为方便起见,我希望在我的本地网络中分配域,而不是Docker容器网络,以便我可以键入以下内容:www.example.com在我的浏览器URL上并加载Docker容器。client.dev on my browsers URL and load the Docker container.
现在,我只能访问如果我使用Docker IP,这是动态的:

client: 192.168.99.100:80
server: 192.168.99.100:3000
database: 192.168.99.100:5432

有没有一种自动/方便的方法来完成这项工作,而不需要我手动将IP添加到我的/etc/hosts文件?
顺便说一句,我在OSX上,如果这有任何相关性。
谢谢!

据我所知,他们似乎说,这是不可用的东西以外的框,他们建议外部工具,如:

是这样吗?如果是这样,在我的特定场景中,我应该选择哪一个?

vdgimpew

vdgimpew1#

由于似乎没有原生的方法来使用Docker完成此操作,我最终选择了Ryan Armstrong的alternate solution,它包括动态更新/etc/hosts文件。
我选择这个是因为它对我来说很方便,因为它是一个脚本,而且我已经有了一个启动脚本,所以我可以把这个函数附加到它上面。
以下示例创建一个名为docker.local的主机条目,该条目将解析为您的docker-machine IP:

update-docker-host(){
    # clear existing docker.local entry from /etc/hosts
    sudo sed -i '' '/[[:space:]]docker\.local$/d' /etc/hosts

    # get ip of running machine
    export DOCKER_IP="$(echo ${DOCKER_HOST} | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')"

    # update /etc/hosts with docker machine ip
    [[ -n $DOCKER_IP ]] && sudo /bin/bash -c "echo \"${DOCKER_IP}   docker.local\" >> /etc/hosts"
}

update-docker-host

当我通过启动脚本启动Docker机器时,这将自动添加或更新主机操作系统上的/etc/hosts行。
无论如何,正如我在研究过程中发现的,除了编辑hosts文件之外,您还可以通过setting up a custom DNS server解决此问题:
我还在Github上找到了几个显然旨在解决这个问题的项目,尽管我没有尝试它们:

pvcm50d1

pvcm50d12#

扩展@eduwass自己的答案,下面是我手动做的(没有脚本)。
1.如问题中所述,在docker-compose.yml文件中定义domainname: myapp.devhostname: www
1.把你们的码头集装箱正常带上来
1.运行docker-compose exec client cat /etc/hosts以获取容器的hosts文件的输出(其中client是您的服务名称)(输出示例:172.18.0.6 www.myapp.dev
1.打开本地(主机)/etc/hosts文件并添加以下行:172.18.0.6 server.server.dev
如果您的Docker服务容器更改了IP或做了任何花哨的事情,您会想要一个更复杂的解决方案,但目前这只是为我的简单需求工作。

eivgtgni

eivgtgni3#

另一种解决方案是使用带有代理扩展的浏览器,通过代理容器发送请求,代理容器知道将域解析到哪里。如果您考虑将jwilder/nginx-proxy用于生产模式,那么您的问题可以通过mitm-nginx-proxy-companion轻松解决。
以下是基于原始堆栈的示例:

version: '3.3'

services:

  server:
    build: ./server
    working_dir: /app
    volumes:
      - ./server:/app

  client:
    environment:
      - VIRTUAL_HOST: client.dev
    image: php:5.6-apache
    volumes:
    - ./client:/var/www/html

  database:
    image: postgres:9.4
    restart: always
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=root
      - POSTGRES_DB=dbdev
      - PG_TRUST_LOCALNET=true
    volumes:
      - ./database/scripts:/docker-entrypoint-initdb.d # init scripts

  nginx-proxy:
    image: jwilder/nginx-proxy
    labels:
      - "mitmproxy.proxyVirtualHosts=true"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro

  nginx-proxy-mitm:
    dns:
      - 127.0.0.1
    image: artemkloko/mitm-nginx-proxy-companion
    ports:
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
  • 运行docker-compose up
  • 在浏览器中添加代理扩展,代理地址为127.0.0.1:8080
  • 访问http://client.dev

请求将遵循以下路径:

  • 在浏览器中访问本地开发域
  • 代理扩展将该请求转发到mitm-nginx-proxy-companion,而不是"真正的" Internet
  • mitm-nginx-proxy-companion尝试通过同一容器中的dns服务器解析域名
  • 如果该域不是"本地"域,它会将请求转发到"真正的"互联网
  • 但是,如果域是"本地"域,则它会将请求转发到nginx-proxy
  • nginx-proxy依次将请求转发到包含我们要访问的服务的适当容器

旁注:

  • 删除了links,因为它已过时,并已被Docker Networks取代
  • 你不需要添加域名到serverdatabase容器。client将能够在serverdatabase域上访问它们,因为它们都在同一个网络中(类似于link以前所做的)
  • 你不需要在serverdatabase容器上使用ports,因为它只转发要通过127.0.0.1使用的端口。client容器中的PHP只会对其他容器执行"后端"请求,并且因为这些容器在同一个网络中,您已经可以使用database:5432server:3000访问它们。server <-> database连接也是如此。
  • 我是mitm-nginx-proxy-companion的作者
9w11ddsr

9w11ddsr4#

为了使整个域为localhost,您可以使用dnsmasq。在这种情况下,如果您选择域**.dev**,则任何子域都将指向您的容器。但您必须了解具有**.dev**区域的problems
或者,您可以使用bash脚本来启动您的docker-compose,它在启动时会向/etc/hosts添加一行,在您终止此进程后,该行将被删除

#!/usr/bin/env bash

sudo sed -i '1s;^;127.0.0.1    example.dev\n;' /etc/hosts

trap 'sudo sed -i "/example.dev/d" /etc/hosts' 2

docker-compose up
0dxa2lsx

0dxa2lsx5#

基于http://cavaliercoder.com/blog/update-etc-hosts-for-docker-machine.html的Bash脚本WITH ALIAS而不使用docker-machine

#!/bin/bash

#alias
declare -A aliasArr
aliasArr[docker_name]="alias1,alias2"

# clear existing *.docker.local entries from /etc/hosts
sudo sed -i '/\.docker\.local$/d' /etc/hosts

# iterate over each machine
docker ps -a --format "{{.Names}}" \
| while read -r MACHINE; do

    MACHINE_IP="$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ${MACHINE} 2>/dev/null)"
    
    if [[ ${aliasArr[$MACHINE]} ]]
    then
        DOMAIN_NAME=$(echo ${aliasArr[$MACHINE]} | tr "," "\n")
    else
        DOMAIN_NAME=( ${MACHINE} )
    fi

    for addr in $DOMAIN_NAME
    do
        echo "add ${MACHINE_IP} ${addr}.docker.local"
        [[ -n $MACHINE_IP ]] && sudo /bin/bash -c "echo \"${MACHINE_IP} ${addr}.docker.local\" >> /etc/hosts"
        export no_proxy=$no_proxy,$MACHINE_IP
    done
        
done

相关问题