@T0xicCode的答案是正确的,但是我认为我会扩展细节,因为实际上花了大约20个小时才能最终实现可行的解决方案。
如果您希望在自己的容器中运行Nginx并将其用作反向代理,以在同一服务器实例上负载均衡多个应用程序,那么您需要遵循的步骤如下:
链接您的容器
当
docker run您使用容器时,通常可以通过在中输入shell脚本
User Data来声明指向任何其他 _正在运行的_容器的链接。这意味着您需要按顺序启动容器,只有后者才能链接到前者。像这样:
#!/bin/bashsudo docker run -p 3000:3000 --name API mydockerhub/apisudo docker run -p 3001:3001 --link API:API --name App mydockerhub/appsudo docker run -p 80:80 -p 443:443 --link API:API --link App:App --name Nginx mydockerhub/nginx
因此,在此示例中,该
API容器未链接到任何其他
App容器,但是该 容器已链接到
API并且
Nginx链接到
API和
App。
其结果是更改了
envvars和
/etc/hosts位于
APIand
App容器内的文件。结果看起来像这样:
/ etc / hosts
cat /etc/hosts在您的
Nginx容器中运行将产生以下结果:
172.17.0.5 0fd9a40ab5ec127.0.0.1 localhost::1 localhost ip6-localhost ip6-loopbackfe00::0 ip6-localnetff00::0 ip6-mcastprefixff02::1 ip6-allnodesff02::2 ip6-allrouters172.17.0.3 App172.17.0.2 API
ENV Vars
env在您的
Nginx容器中运行将产生以下结果:
API_PORT=tcp://172.17.0.2:3000API_PORT_3000_TCP_PROTO=tcpAPI_PORT_3000_TCP_PORT=3000API_PORT_3000_TCP_ADDR=172.17.0.2APP_PORT=tcp://172.17.0.3:3001APP_PORT_3001_TCP_PROTO=tcpAPP_PORT_3001_TCP_PORT=3001APP_PORT_3001_TCP_ADDR=172.17.0.3
我已经截断了许多实际的var,但是以上是将流量代理到容器所需的键值。
要获取一个shell在运行中的容器中运行上述命令,请使用以下命令:
sudo docker exec -i -t Nginx bash
您可以看到,您现在同时具有
/etc/hosts文件条目和
envvar,它们包含所链接的任何容器的本地IP地址。据我所知,这是在运行带有声明的链接选项的容器时发生的所有情况。但是您现在可以使用此信息
nginx在
Nginx容器中进行配置。
配置Nginx
这是个棘手的地方,有两种选择。您可以选择将站点配置为指向
/etc/hosts所
docker创建文件中的条目,或者可以使用
ENVvars
sed对
nginx.conf文件
/etc/nginx/sites-enabled夹中的conf文件和其他任何conf文件运行字符串替换(我用过)以插入IP。价值观。
选项A:使用ENV Vars配置Nginx
这是我选择的选项,因为我无法使用
/etc/hostsfile选项。我将尽快尝试选项B,并用任何发现更新本文。
此选项与使用
/etc/hosts文件选项之间的主要区别在于,如何编写
Dockerfile脚本以使用shell脚本作为
CMD参数,而该脚本又处理字符串替换以将IP值复制
ENV到conf文件中。
这是我最终得到的一组配置文件:
Docker文件
FROM ubuntu:14.04MAINTAINER Your Name <you@myapp.com>RUN apt-get update && apt-get install -y nano htop git nginxADD nginx.conf /etc/nginx/nginx.confADD api.myapp.conf /etc/nginx/sites-enabled/api.myapp.confADD app.myapp.conf /etc/nginx/sites-enabled/app.myapp.confADD Nginx-Startup.sh /etc/nginx/Nginx-Startup.shEXPOSE 80 443CMD ["/bin/bash","/etc/nginx/Nginx-Startup.sh"]
nginx.conf
daemon off;user www-data;pid /var/run/nginx.pid;worker_processes 1;events { worker_connections 1024;}http { # Basic Settings sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 33; types_hash_max_size 2048; server_tokens off; server_names_hash_bucket_size 64; include /etc/nginx/mime.types; default_type application/octet-stream; # Logging Settings access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; # Gzip Settingsgzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 3; gzip_buffers 16 8k; gzip_http_version 1.1; gzip_types text/plain text/xml text/css application/x-javascript application/json; gzip_disable "MSIE [1-6].(?!.*SV1)"; # Virtual Host Configs include /etc/nginx/sites-enabled/*; # Error Page Config #error_page 403 404 500 502 /srv/Splash;}注意:重要的是要包含
daemon off;在nginx.conf文件中,以确保容器在启动后不会立即退出。
api.myapp.conf
upstream api_upstream{ server APP_IP:3000;}server { listen 80; server_name api.myapp.com; return 301 https://api.myapp.com/$request_uri;}server { listen 443; server_name api.myapp.com; location / { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; proxy_pass http://api_upstream; }}Nginx-Startup.sh
#!/bin/bashsed -i 's/APP_IP/'"$API_PORT_3000_TCP_ADDR"'/g' /etc/nginx/sites-enabled/api.myapp.comsed -i 's/APP_IP/'"$APP_PORT_3001_TCP_ADDR"'/g' /etc/nginx/sites-enabled/app.myapp.comservice nginx start
我把它留给你做你的最多的内容作业
nginx.conf和
api.myapp.conf。
魔术发生在
Nginx-Startup.sh我们用来
sed在
APP_IP已写入到文件和文件
upstream块中的占位符上进行字符串替换的地方。
api.myapp.conf``app.myapp.conf
这个ask.ubuntu.com问题很好地说明了这一点:
使用命令在文件中查找和替换文本
GOTCHA
在OSX上,以sed不同方式处理选项,特别是-i标志。在Ubuntu上,该-i标志将处理“就地”替换;它将打开文件,更改文本,然后“保存”相同的文件。在OSX上,该-i标志
需要 您想要结果文件具有的文件扩展名。如果使用的文件没有扩展名,则必须输入’‘作为-i标志值。GOTCHA
要在sed用于查找要替换的字符串的正则表达式中使用ENV变量,需要将变量包装在双引号中。因此,正确的,尽管看上去有些古怪的语法如上所述。
因此docker启动了我们的容器并触发了
Nginx-Startup.sh脚本运行,该脚本用于
sed将值更改为我们在命令中提供
APP_IP的相应
ENV变量
sed。现在我们的
/etc/nginx/sites-enabled目录中有conf文件,这些文件具有
ENVdocker在启动容器时设置的vars
的IP地址。在
api.myapp.conf文件中,您将看到
upstream块已更改为:
upstream api_upstream{ server 172.0.0.2:3000;}您看到的IP地址可能有所不同,但我注意到它通常是
172.0.0.x。
现在,您应该正确路由所有路由。
GOTCHA
运行初始实例启动后,您将无法重新启动/重新运行任何容器。Docker在启动时为每个容器提供了一个新IP,并且似乎没有重复使用以前使用的任何容器。因此api.myapp.com,第一次将获得172.0.0.2,但是下次将获得172.0.0.4。但是Nginx将已经在其conf文件或该/etc/hosts文件中设置了第一个IP
,因此它将无法确定的新IPapi.myapp.com。据我有限的理解,此解决方案很可能会使用CoreOS其etcd服务,并且它的服务就像ENV注册到同一CoreOS集群的所有计算机的共享一样。这是我要设置的下一个玩具。
选项B:使用/etc/hosts
文件条目
这 应该
是更快,更轻松的方法,但是我无法使其正常工作。从表面上看,您只是将
/etc/hosts条目的值输入到您的
api.myapp.conf和
app.myapp.conf文件中,但是我无法使用此方法。
这是我所做的尝试
api.myapp.conf:
upstream api_upstream{ server API:3000;}考虑到我的
/etc/hosts文件中有一个这样的条目:
172.0.0.2API我认为它只会提取值,但似乎没有。
我
Elastic LoadBalancer从所有可用区的采购也遇到了一些辅助问题,因此当我尝试此路线时可能就是问题所在。相反,我不得不学习如何在Linux中处理替换字符串,所以这很有趣。我将在一段时间内尝试一下,看看效果如何。



