├── .gitignore ├── Dockerfile ├── Dockerfile-alpine ├── LICENSE ├── README.md ├── etc ├── nginx │ ├── conf.d │ │ └── default.conf │ └── nginx.conf └── services.d │ └── consul-template │ └── run ├── logo.png └── sample ├── README.md ├── docker-compose.yml └── etc └── consul-template ├── conf └── app.conf └── templates └── app.ctmpl /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Nginx image with Consul Template 3 | # 4 | FROM nginx:1.13 5 | MAINTAINER 1science Devops Team 6 | 7 | RUN apt-get update && apt-get install -y curl unzip less vim 8 | 9 | # Consul template for configuration management 10 | ENV S6_OVERLAY_VERSION=1.19.1.1 CONSUL_TEMPLATE_VERSION=0.18.2 11 | 12 | # Install S6 Overlay and Consul Template 13 | RUN curl -Ls https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-amd64.tar.gz | tar -xz -C / 14 | RUN curl -Ls https://releases.hashicorp.com/consul-template/${CONSUL_TEMPLATE_VERSION}/consul-template_${CONSUL_TEMPLATE_VERSION}_linux_amd64.zip -o consul-template.zip && \ 15 | unzip consul-template.zip -d /usr/local/bin && \ 16 | rm -f consul-template* && \ 17 | echo -ne "- with `consul-template -v 2>&1`\n" >> /root/.built 18 | 19 | # Add services configuration 20 | ADD etc /etc 21 | 22 | ENTRYPOINT ["/init"] 23 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /Dockerfile-alpine: -------------------------------------------------------------------------------- 1 | # 2 | # Nginx image with Consul Template, based on Alpine Linux 3 | # 4 | FROM nginx:1.13-alpine 5 | MAINTAINER 1science Devops Team 6 | 7 | RUN apk update && apk upgrade && \ 8 | apk add curl wget bash tree unzip less vim 9 | 10 | # Consul template for configuration management 11 | ENV S6_OVERLAY_VERSION=1.19.1.1 CONSUL_TEMPLATE_VERSION=0.18.2 12 | 13 | # Install S6 Overlay and Consul Template 14 | RUN curl -Ls https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-amd64.tar.gz | tar -xz -C / 15 | RUN curl -Ls https://releases.hashicorp.com/consul-template/${CONSUL_TEMPLATE_VERSION}/consul-template_${CONSUL_TEMPLATE_VERSION}_linux_amd64.zip -o consul-template.zip && \ 16 | unzip consul-template.zip -d /usr/local/bin && \ 17 | rm -f consul-template* && \ 18 | echo -ne "- with `consul-template -v 2>&1`\n" >> /root/.built 19 | 20 | # Add services configuration 21 | ADD /etc /etc 22 | 23 | ENTRYPOINT ["/init"] 24 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 1science Devops Team 2 | 3 | Permission to use, copy, modify, and distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DEPRECATED 2 | 3 | [![](https://badge.imagelayers.io/1science/nginx:consul.svg)](https://imagelayers.io/?images=1science/nginx 'Get your own badge on imagelayers.io') 4 | 5 | # Consul Nginx image 6 | 7 | This image inherits from the ```nginx``` image adding support to manage the Nginx configuration through [Consul](https://consul.io/) 8 | 9 | It includes : 10 | - [S6 Overlay](https://github.com/just-containers/s6-overlay) to properly manage multiple services in one container 11 | - [Consul template](https://github.com/hashicorp/consul-template) to manage dynamic configuration based on Consul 12 | 13 | # Usage 14 | 15 | **Consul Template** 16 | 17 | The following example mount the [Consul template](https://github.com/hashicorp/consul-template) configuration in the container: 18 | 19 | ``` 20 | docker run --name nginx-consul -v etc/consul-template:/etc/consul-template:ro -d 1science/nginx:consul 21 | 22 | ``` 23 | 24 | or you can create your own ```Dockerfile```: 25 | 26 | ``` 27 | FROM 1science/nginx:consul 28 | 29 | ADD etc/consul-template /etc/consul-template 30 | ``` 31 | 32 | # Variants 33 | 34 | An image based on the lightweight [Alpine Linux](https://alpinelinux.org/) distribution is available with the tag ```{version}-alpine```. 35 | 36 | # Load Balancing Sample 37 | 38 | The [sample application](sample) demonstrate how to achieve load balancing with Nginx, [Consul](https://www.consul.io/) and [Registrator](http://progrium.com/blog/2014/09/10/automatic-docker-service-announcement-with-registrator/). 39 | 40 | # Thanks 41 | 42 | We would like to thanks [John Regan](https://github.com/jprjr) for his work on the [S6 system init](http://blog.tutum.co/2015/05/20/s6-made-easy-with-the-s6-overlay/) which is just awesome. 43 | 44 | # Build 45 | 46 | This project is configured as an [automated build in Dockerhub](https://hub.docker.com/r/1science/nginx/). 47 | 48 | Each branch give the related image tag. 49 | 50 | # License 51 | 52 | All the code contained in this repository, unless explicitly stated, is 53 | licensed under ISC license. 54 | 55 | A copy of the license can be found inside the [LICENSE](LICENSE) file. 56 | -------------------------------------------------------------------------------- /etc/nginx/conf.d/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | #charset koi8-r; 6 | #access_log /var/log/nginx/log/host.access.log main; 7 | 8 | location / { 9 | root /usr/share/nginx/html; 10 | index index.html index.htm; 11 | } 12 | 13 | #error_page 404 /404.html; 14 | 15 | # redirect server error pages to the static page /50x.html 16 | # 17 | error_page 500 502 503 504 /50x.html; 18 | location = /50x.html { 19 | root /usr/share/nginx/html; 20 | } 21 | 22 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 23 | # 24 | #location ~ \.php$ { 25 | # proxy_pass http://127.0.0.1; 26 | #} 27 | 28 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 29 | # 30 | #location ~ \.php$ { 31 | # root html; 32 | # fastcgi_pass 127.0.0.1:9000; 33 | # fastcgi_index index.php; 34 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 35 | # include fastcgi_params; 36 | #} 37 | 38 | # deny access to .htaccess files, if Apache's document root 39 | # concurs with nginx's one 40 | # 41 | #location ~ /\.ht { 42 | # deny all; 43 | #} 44 | } -------------------------------------------------------------------------------- /etc/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | # Default Nginx configuration loading sites from /etc/nginx/conf.d directory 2 | worker_processes 1; 3 | 4 | error_log /var/log/nginx/error.log warn; 5 | pid /var/run/nginx.pid; 6 | 7 | 8 | events { 9 | worker_connections 1024; 10 | } 11 | 12 | 13 | http { 14 | include /etc/nginx/mime.types; 15 | default_type application/octet-stream; 16 | 17 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 18 | '$status $body_bytes_sent "$http_referer" ' 19 | '"$http_user_agent" "$http_x_forwarded_for"'; 20 | 21 | access_log /var/log/nginx/access.log main; 22 | 23 | sendfile on; 24 | #tcp_nopush on; 25 | 26 | keepalive_timeout 65; 27 | 28 | #gzip on; 29 | 30 | include /etc/nginx/conf.d/*.conf; 31 | } -------------------------------------------------------------------------------- /etc/services.d/consul-template/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/with-contenv sh 2 | set -e 3 | 4 | if [ -z ${RUN_ON_AWS} ]; then 5 | CONSUL_URL=${CONSUL_URL:-localhost:8500} 6 | else 7 | # Resolve the EC2 IP running a Consul Agent through API 8 | # This a workaround for this issue : https://github.com/aws/amazon-ecs-agent/issues/185 9 | HOST_IP=$(curl http://169.254.169.254/latest/meta-data/local-hostname) 10 | CONSUL_URL="$HOST_IP:8500" 11 | fi 12 | 13 | if [ -d /etc/consul-template/conf ]; then 14 | exec consul-template \ 15 | -consul ${CONSUL_URL} \ 16 | -config "/etc/consul-template/conf" 17 | fi -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elsevier-research/docker-nginx/b4d0db4d3bec6d1427187df068b1e0ada99c7f45/logo.png -------------------------------------------------------------------------------- /sample/README.md: -------------------------------------------------------------------------------- 1 | # How to setup Nginx as a dynamic load balancer ? 2 | 3 | The following application demonstrate how to setup a dynamic load balancing with : 4 | 5 | - [Nginx](http://nginx.org/en/docs/http/load_balancing.html) as a load balancer 6 | - [Consul](http://progrium.com/blog/2014/08/20/consul-service-discovery-with-docker/) as service registry 7 | - [Registrator](http://progrium.com/blog/2014/09/10/automatic-docker-service-announcement-with-registrator/) as service registrator 8 | - [Hello World application](https://github.com/tutumcloud/docker-hello-world) as sample application 9 | 10 | 11 | # How to use ? 12 | 13 | 14 | First of all you have to install [Consul](https://www.consul.io/intro/getting-started/install.html) and [Consul UI](https://www.consul.io/downloads.html). 15 | 16 | 17 | Then you have to start Consul as an agent server on the docker host. 18 | 19 | ``` 20 | consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -ui-dir /usr/local/share/consul --client 0.0.0.0 21 | ``` 22 | 23 | Then you can start the services : 24 | 25 | ``` 26 | docker-compose up 27 | ``` 28 | 29 | This should start all services defined in ```docker-compose.yml```. 30 | 31 | 32 | The sample app should be running and being available at ```http://localhost/```, displaying the hostname of the container serving the application. 33 | 34 | 35 | Now we want to scale up the sample application : 36 | 37 | ``` 38 | docker-compose scale app=5 39 | ``` 40 | 41 | and we can see refreshing the sample app in your favorite browser, the hostname should change. 42 | 43 | 44 | If you check the Consul UI located at ```http://localhost:8500/ui```, you you should see 5 instances of the sample application (named app). 45 | 46 | 47 | Now we can scale down the sample application : 48 | 49 | ``` 50 | docker-compose scale app=1 51 | ``` 52 | 53 | and the containers should be stopped and destroyed. 54 | 55 | 56 | # How it works ? 57 | 58 | The [registrator](https://github.com/gliderlabs/registrator) container is responsable for registering and deregistering services based on container start and die events from Docker. 59 | 60 | The [consul](https://github.com/progrium/docker-consul) container maintain the service registry. 61 | 62 | The [nginx](https://github.com/1science/docker-nginx) use [S6](http://skarnet.org/software/s6/) as system init to run nginx and [consul-template](https://github.com/hashicorp/consul-template) in the same container. 63 | 64 | The role of consul-template is to generate a valid nginx configuration file in ```/etc/nginx/conf.d``` directory based on a [template](templates/app.conf) and reload Nginx when new services are registered in Consul. 65 | 66 | 67 | # Thanks 68 | 69 | We would like to thanks : 70 | 71 | - [Jeff Lindsay](http://progrium.com/) for the fantastic work he did for building [registrator](https://github.com/gliderlabs/registrator) and [consul](https://github.com/progrium/docker-consul) docker images. 72 | - [John Regan](https://github.com/jprjr) for his article on [S6 system init](http://blog.tutum.co/2014/12/02/docker-and-s6-my-new-favorite-process-supervisor/) which is a great system init. 73 | - [Shane Sveller]() from [Tutum](https://www.tutum.co/) for his article on [load balancing with Nginx and consul-template]( https://tech.bellycard.com/blog/load-balancing-docker-containers-with-nginx-and-consul-template/) which inspired this prototype 74 | -------------------------------------------------------------------------------- /sample/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # Sample application 2 | app: 3 | image: tutum/hello-world:latest 4 | environment: 5 | # Environment variables used by registrator to register services in consul 6 | SERVICE_NAME: app 7 | SERVICE_TAGS: sample 8 | ports: 9 | - 80 10 | 11 | # Nginx Load Balancer 12 | lb: 13 | image: 1science/nginx:1.9.6-consul 14 | ports: 15 | - 80:80 16 | volumes: 17 | - ./etc/consul-template:/etc/consul-template 18 | # Change this section to point on your Consul 19 | environment: 20 | CONSUL_URL: localhost:8500 21 | net: "host" 22 | 23 | # Registrator to register on local Consul 24 | registrator: 25 | image: gliderlabs/registrator:latest 26 | volumes: 27 | - /var/run/docker.sock:/tmp/docker.sock 28 | # Change this section to point on your Consul 29 | command: consul://localhost:8500 30 | net: "host" 31 | -------------------------------------------------------------------------------- /sample/etc/consul-template/conf/app.conf: -------------------------------------------------------------------------------- 1 | template { 2 | source = "/etc/consul-template/templates/app.ctmpl" 3 | destination = "/etc/nginx/conf.d/app.conf" 4 | command = "nginx -s reload" 5 | } -------------------------------------------------------------------------------- /sample/etc/consul-template/templates/app.ctmpl: -------------------------------------------------------------------------------- 1 | upstream app { 2 | least_conn; 3 | {{range service "sample.app"}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1; 4 | {{else}}server 127.0.0.1:65535; # force a 502{{end}} 5 | } 6 | 7 | server { 8 | listen 80 default_server; 9 | 10 | location / { 11 | proxy_pass http://app; 12 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 13 | proxy_set_header Host $host; 14 | proxy_set_header X-Real-IP $remote_addr; 15 | } 16 | } --------------------------------------------------------------------------------