La risposta di @ T0xicCode è corretta, ma ho pensato di espandere i dettagli poiché in realtà mi ci sono volute circa 20 ore per ottenere finalmente l'implementazione di una soluzione funzionante.
Se stai cercando di eseguire Nginx nel proprio contenitore e usarlo come proxy inverso per bilanciare il carico di più applicazioni sulla stessa istanza del server, i passaggi che devi seguire sono i seguenti:
Collega i tuoi contenitori
Quando si utilizzano i docker runcontenitori, in genere inserendo uno script di shell User Data, è possibile dichiarare collegamenti a qualsiasi altro contenitore in esecuzione . Ciò significa che è necessario avviare i contenitori in ordine e solo questi ultimi possono collegarsi ai primi. Così:
#!/bin/bash
sudo docker run -p 3000:3000 --name API mydockerhub/api
sudo docker run -p 3001:3001 --link API:API --name App mydockerhub/app
sudo docker run -p 80:80 -p 443:443 --link API:API --link App:App --name Nginx mydockerhub/nginx
Quindi, in questo esempio, il APIcontenitore non è collegato a nessun altro, ma il
Appcontenitore è collegato APIed Nginxè collegato a entrambi APIe App.
Il risultato di ciò sono le modifiche alle envvariabili e ai /etc/hostsfile che risiedono nei contenitori APIe App. I risultati sono così:
/ etc / hosts
L'esecuzione cat /etc/hostsall'interno del tuo Nginxcontainer produrrà quanto segue:
172.17.0.5 0fd9a40ab5ec
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 App
172.17.0.2 API
ENV Vars
L'esecuzione envall'interno del tuo Nginxcontainer produrrà quanto segue:
API_PORT=tcp://172.17.0.2:3000
API_PORT_3000_TCP_PROTO=tcp
API_PORT_3000_TCP_PORT=3000
API_PORT_3000_TCP_ADDR=172.17.0.2
APP_PORT=tcp://172.17.0.3:3001
APP_PORT_3001_TCP_PROTO=tcp
APP_PORT_3001_TCP_PORT=3001
APP_PORT_3001_TCP_ADDR=172.17.0.3
Ho troncato molte delle variabili effettive, ma i valori sopra riportati sono i valori chiave di cui hai bisogno per proxy del traffico ai tuoi contenitori.
Per ottenere una shell per eseguire i comandi precedenti all'interno di un contenitore in esecuzione, utilizzare quanto segue:
sudo docker exec -i -t Nginx bash
Puoi vedere che ora hai sia /etc/hostsvoci di file envche variabili che contengono l'indirizzo IP locale per uno dei contenitori che erano collegati. Per quanto ne so, questo è tutto ciò che accade quando esegui contenitori con opzioni di collegamento dichiarate. Ma ora puoi utilizzare queste informazioni per configurare nginxall'interno del tuo Nginxcontenitore.
Configurazione di Nginx
È qui che diventa un po 'complicato e ci sono un paio di opzioni. Puoi scegliere di configurare i tuoi siti in modo che puntino a una voce nel /etc/hostsfile che dockerhai creato, oppure puoi utilizzare le ENVvariabili ed eseguire una sostituzione di stringa (io ho usato sed) sul tuo nginx.confe su qualsiasi altro file di configurazione che potrebbe essere nella tua /etc/nginx/sites-enabledcartella per inserire l'IP valori.
OPZIONE A: Configura Nginx usando ENV Vars
Questa è l'opzione che ho scelto perché non sono riuscito a far funzionare l'
/etc/hostsopzione file. Proverò abbastanza presto l'opzione B e aggiornerò questo post con eventuali risultati.
La differenza fondamentale tra questa opzione e l'utilizzo /etc/hostsdell'opzione file è il modo in cui scrivi il tuo Dockerfileper utilizzare uno script di shell come CMDargomento, che a sua volta gestisce la sostituzione della stringa per copiare i valori IP dai ENVtuoi file di configurazione.
Ecco il set di file di configurazione con cui sono finito:
Dockerfile
FROM ubuntu:14.04
MAINTAINER Your Name <you@myapp.com>
RUN apt-get update && apt-get install -y nano htop git nginx
ADD nginx.conf /etc/nginx/nginx.conf
ADD api.myapp.conf /etc/nginx/sites-enabled/api.myapp.conf
ADD app.myapp.conf /etc/nginx/sites-enabled/app.myapp.conf
ADD Nginx-Startup.sh /etc/nginx/Nginx-Startup.sh
EXPOSE 80 443
CMD ["/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 Settings
gzip 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;
}
NOTA: è importante includerlo daemon off;nel nginx.conffile per assicurarsi che il contenitore non venga chiuso immediatamente dopo l'avvio.
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/bash
sed -i 's/APP_IP/'"$API_PORT_3000_TCP_ADDR"'/g' /etc/nginx/sites-enabled/api.myapp.com
sed -i 's/APP_IP/'"$APP_PORT_3001_TCP_ADDR"'/g' /etc/nginx/sites-enabled/app.myapp.com
service nginx start
Lascio a te il compito di fare i compiti sulla maggior parte dei contenuti di nginx.confe api.myapp.conf.
La magia accade Nginx-Startup.shquando usiamo sedper sostituire la stringa sul APP_IPsegnaposto che abbiamo scritto nel upstreamblocco dei nostri file api.myapp.confe app.myapp.conf.
Questa domanda di ask.ubuntu.com lo spiega molto bene:
trova e sostituisci il testo all'interno di un file usando i comandi
GOTCHA
Su OSX, sedgestisce le opzioni in modo diverso, -ispecificatamente il flag. Su Ubuntu, il -iflag gestirà la sostituzione "sul posto"; aprirà il file, cambierà il testo e quindi "salverà" lo stesso file. Su OSX, il -iflag richiede l'estensione del file che desideri abbia il file risultante. Se stai lavorando con un file che non ha estensione, devi inserire "" come valore per il -iflag.
GOTCHA
Per usare ENV vars all'interno della regex che sedusa per trovare la stringa che vuoi sostituire, devi racchiudere la var tra virgolette doppie. Quindi la sintassi corretta, anche se dall'aspetto traballante, è come sopra.
Quindi docker ha avviato il nostro contenitore e attivato lo Nginx-Startup.shscript da eseguire, che ha utilizzato sedper modificare il valore APP_IPnella ENVvariabile corrispondente che abbiamo fornito nel sedcomando. Ora abbiamo i file di configurazione all'interno della nostra /etc/nginx/sites-enableddirectory che hanno gli indirizzi IP delle ENVvariabili che docker ha impostato all'avvio del contenitore. All'interno del tuo api.myapp.conffile vedrai che il upstreamblocco è cambiato in questo:
upstream api_upstream{
server 172.0.0.2:3000;
}
L'indirizzo IP che vedi potrebbe essere diverso, ma ho notato che di solito è 172.0.0.x.
Ora dovresti avere tutto il routing in modo appropriato.
GOTCHA
Non è possibile riavviare / rieseguire alcun container dopo aver eseguito l'avvio iniziale dell'istanza. Docker fornisce a ciascun container un nuovo IP all'avvio e non sembra riutilizzare nessuno di quelli utilizzati in precedenza. Quindi api.myapp.comotterrai 172.0.0.2 la prima volta, ma poi 172.0.0.4 la volta successiva. Ma Nginxavrà già impostato il primo IP nei suoi file di configurazione, o nel suo /etc/hostsfile, quindi non sarà in grado di determinare il nuovo IP per api.myapp.com. La soluzione a questo è probabile che utilizzi CoreOSe il suo etcdservizio che, nella mia comprensione limitata, agisce come uno condiviso ENVper tutte le macchine registrate nello stesso CoreOScluster. Questo è il prossimo giocattolo con cui giocherò.
OPZIONE B: Usa /etc/hostsvoci di file
Questo dovrebbe essere il modo più semplice e veloce per farlo, ma non sono riuscito a farlo funzionare. Apparentemente hai appena inserito il valore della /etc/hostsvoce nei tuoi file api.myapp.confe app.myapp.conf, ma non sono riuscito a far funzionare questo metodo.
AGGIORNAMENTO:
Vedi la risposta di @Wes Tod per le istruzioni su come far funzionare questo metodo.
Ecco il tentativo che ho fatto in api.myapp.conf:
upstream api_upstream{
server API:3000;
}
Considerando che c'è una voce nel mio /etc/hostsfile in questo modo: 172.0.0.2 APIho pensato che avrebbe semplicemente inserito il valore, ma non sembra esserlo.
Ho anche avuto un paio di problemi accessori con il mio Elastic Load Balancerapprovvigionamento da tutte le AZ, quindi questo potrebbe essere stato il problema quando ho provato questo percorso. Invece ho dovuto imparare a gestire la sostituzione delle stringhe in Linux, quindi è stato divertente. Ci proverò tra un po 'e vedrò come va.