初学者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内部网络),例如这里我正在{{1} ping server.dev
CLI:
client.dev
这在内部效果很好,但在主机操作系统网络上却不行。
为方便起见,我想在我的本地网络中分配域,而不是Docker容器网络,以便我可以在浏览器URL上键入:client.dev并加载Docker容器。
现在,我只能在使用Docker IP时访问,这是动态的:
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
是否有自动/方便的方法来执行此操作,而不涉及我手动将IP添加到我的/ etc / hosts文件中?
顺便说一句,如果有任何相关性,我会使用OSX。
谢谢!
修改:我发现这个似乎有关的Github问题:https://github.com/docker/docker/issues/2335
据我了解,他们似乎表示这是一种不可用的东西,他们建议使用外部工具:
这是对的吗?如果是这样,我应该在特定情况下选择哪一个?
答案 0 :(得分:21)
行,
所以自it seems that there is no native way to do this with Docker以来,我终于选择了来自Ryan Armstrong的alternate solution,其中包括动态更新/etc/hosts
文件。
我选择了这个,因为它对我来说很方便,因为它可以用作脚本,而且我已经有了一个启动脚本,所以我可以将这个函数添加到它中。
以下示例创建一个名为docker.local的主机条目 将解析你的码头机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
行。
无论如何,正如我在研究期间发现的那样,除了编辑主机文件外,你还可以通过setting up a custom DNS server来解决这个问题:
在Github上也找到了几个项目,显然是为了解决这个问题,虽然我没有尝试过:
答案 1 :(得分:10)
扩展@ eduwass自己的答案,这是我手动完成的(没有脚本)。
domainname: myapp.dev
文件中定义hostname: www
和docker-compose.yml
docker-compose exec client cat /etc/hosts
以获取容器主机文件的输出(其中client
是您的服务名称)
(输出示例:172.18.0.6 www.myapp.dev
)/etc/hosts
文件并添加该行:172.18.0.6 server.server.dev
如果你的Docker服务容器改变IP或做任何想象力,你会想要一个更复杂的解决方案,但这对我目前的简单需求是有效的。
答案 2 :(得分:1)
另一种解决方案是使用具有代理扩展名的浏览器通过代理容器发送请求,代理容器将知道将域解析到的位置。如果您考虑将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
而不是“真实”互联网mitm-nginx-proxy-companion
尝试通过同一容器中的dns服务器解析域名
nginx-proxy
nginx-proxy
依次将请求转发到包含我们要访问的服务的适当容器旁注:
links
已过时删除,已由Docker网络取代server
和database
容器中。 client
将能够在server
和database
域上访问它们,因为它们都在同一个网络中(类似于link
之前所做的事情)ports
和server
容器上使用database
,因为它只转发要通过127.0.0.1
使用的端口。 client
容器中的PHP仅会对其他容器执行“后端”请求,并且由于这些容器位于同一网络中,因此您已经可以使用database:5432
和server:3000
访问它们。 server <-> database
连接也是如此。mitm-nginx-proxy-companion
答案 3 :(得分:0)
为了为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
答案 4 :(得分:0)
我的 Bash 脚本带有别名,没有 docker-machine 基于http://cavaliercoder.com/blog/update-etc-hosts-for-docker-machine.html
#!/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