Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
Sinkler committed Oct 12, 2017
0 parents commit ce62b0a
Show file tree
Hide file tree
Showing 14 changed files with 300 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
.idea
.pyc
12 changes: 12 additions & 0 deletions README.md
@@ -0,0 +1,12 @@
# Blue/Green deployment wih Docker compose, Nginx, Consul and Registrator

* Run `docker network create consul` to create a new network;
* Run `docker-compose -f docker-compose-consul.yml up -d` to start Consul and Registrator;
* Open in browser `http://localhost:8500/` to check;
* Run `./deploy.sh` to first run;
* Open in browser `http://localhost/` to check;
* Run `./deploy.sh` to imitate deploying of a new app;
* Open in browser `http://localhost/` to check a new version;
* Run `./rollback.sh` to imitate a rollback;
* Open in browser `http://localhost/` to check an old version;
* Use `python2.7 test.py` in a new terminal to be sure that an app is always online during a deploy/rollback.
9 changes: 9 additions & 0 deletions app/Dockerfile
@@ -0,0 +1,9 @@
FROM nginx:1.11.12

RUN rm /etc/nginx/conf.d/default.conf

ADD app.conf /etc/nginx/conf.d/app.conf

RUN mkdir /app

ADD index.html /app
8 changes: 8 additions & 0 deletions app/app.conf
@@ -0,0 +1,8 @@
server {
listen 80 default_server;
server_name localhost;

location / {
root /app;
}
}
1 change: 1 addition & 0 deletions app/index.html
@@ -0,0 +1 @@
Thu Oct 12 19:46:09 MSK 2017
65 changes: 65 additions & 0 deletions deploy.sh
@@ -0,0 +1,65 @@
#!/usr/bin/env bash

set -e

kv=http://localhost:8500/v1/kv/deploy/backend

if [[ "$(docker images -q app:latest 2> /dev/null)" == "" ]]
then
echo 'Build new app:latest image'
cd app
docker build . -t app:latest
cd ..
fi
if [[ "$(docker images -q app:new 2> /dev/null)" == "" ]]
then
echo 'Build new app:new image'
cd app
docker build . -t app:new
cd ..
fi
docker exec nginx true 2>/dev/null || docker-compose up -d

date > app/index.html

echo 'Build new image'
cd app
docker build . -t app:new
cd ..

echo 'Update green container'
docker-compose up -d green

echo 'Set green container as working'
curl -X PUT -d 'green' ${kv}

echo 'Check new app'
status=$(curl http://localhost -o /dev/null -Isw '%{http_code}\n')
if [[ ${status} != "200" ]]
then
echo 'Bad HTTP response:';
echo ${status};

echo 'Set blue container as working'
curl -X PUT -d 'blue' ${kv}

echo 'Remove new container'
docker tag app:latest app:new

exit 1;
fi

echo 'Set old container as previous'
docker tag app:latest app:previous

echo 'Set new container as latest'
docker tag app:new app:latest

echo 'Update blue container'
docker-compose up -d blue

echo 'Set blue container as working'
curl -X PUT -d 'blue' ${kv}

echo 'Stop green container'
docker-compose stop green
47 changes: 47 additions & 0 deletions docker-compose-consul.yml
@@ -0,0 +1,47 @@
version: '3.1'

# https://www.consul.io/intro/index.html
# http://gliderlabs.github.io/registrator/latest/

services:
consul:
hostname: consul
container_name: consul
image: consul:latest
environment:
- CONSUL_LOCAL_CONFIG={"disable_update_check":true}
entrypoint:
- consul
- agent
- -server
- -bootstrap
- -data-dir=/data
- -bind={{ GetInterfaceIP "eth0" }}
- -client=0.0.0.0
- -ui
volumes:
- consul:/data
networks:
- consul
ports:
- 8500:8500

registrator:
container_name: registrator
command: -internal consul://consul:8500
privileged: true
image: gliderlabs/registrator:latest
links:
- consul
volumes:
- /var/run/docker.sock:/tmp/docker.sock
networks:
- consul

networks:
consul:
external:
name: consul

volumes:
consul:
45 changes: 45 additions & 0 deletions docker-compose.yml
@@ -0,0 +1,45 @@
version: '3.1'

services:
blue:
container_name: blue
image: app:latest
environment:
- SERVICE_80_NAME=blue
- SERVICE_80_TAGS=backends
networks:
- app
- consul

green:
container_name: green
image: app:new
environment:
- SERVICE_80_NAME=green
- SERVICE_80_TAGS=backends
networks:
- app
- consul

nginx:
container_name: nginx
build: ./nginx/
environment:
- SERVICE_NAME=nginx
- SERVICE_TAGS=nginx
external_links:
- consul
links:
- blue
- green
networks:
- app
- consul
ports:
- 80:80

networks:
app:
consul:
external:
name: consul
17 changes: 17 additions & 0 deletions nginx/Dockerfile
@@ -0,0 +1,17 @@
FROM nginx:1.11.12

RUN apt-get update -qqy && apt-get -qqy install curl runit wget unzip && \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*

RUN wget https://releases.hashicorp.com/consul-template/0.19.3/consul-template_0.19.3_linux_amd64.zip && \
unzip -d /usr/local/bin consul-template_0.19.3_linux_amd64.zip && \
rm -rf consul-template_0.19.3_linux_amd64.zip

ADD nginx.service /etc/service/nginx/run
ADD consul-template.service /etc/service/consul-template/run
RUN mkdir /etc/consul-templates
ADD nginx.conf.ctmpl /etc/consul-templates
RUN chmod +x /etc/service/nginx/run && chmod +x /etc/service/consul-template/run
RUN rm /etc/nginx/conf.d/default.conf

CMD ["/usr/bin/runsvdir", "/etc/service"]
5 changes: 5 additions & 0 deletions nginx/consul-template.service
@@ -0,0 +1,5 @@
#!/bin/sh

exec consul-template \
-consul-addr consul:8500 \
-template "/etc/consul-templates/nginx.conf.ctmpl:/etc/nginx/conf.d/nginx.conf:sv hup nginx"
46 changes: 46 additions & 0 deletions nginx/nginx.conf.ctmpl
@@ -0,0 +1,46 @@
upstream blue {
{{ range service "backends.blue" }}
server {{ .Name }}:{{ .Port }};
{{ else }}
{{ range service "backends.green" }}
server {{ .Name }}:{{ .Port }};
{{ else }}
server 127.0.0.1:12345;
{{ end }}
{{ end }}
}

upstream green {
{{ range service "backends.green" }}
server {{ .Name }}:{{ .Port }};
{{ else }}
{{ range service "backends.blue" }}
server {{ .Name }}:{{ .Port }};
{{ else }}
server 127.0.0.1:12345;
{{ end }}
{{ end }}
}

server {
listen 80 default_server;
server_name localhost;

location / {
add_header Pragma no-cache;
add_header Cache-Control no-cache;
{{ with $key_value := keyOrDefault "deploy/backend" "blue" }}
{{ if or (eq $key_value "blue") (eq $key_value "green") }}
proxy_pass http://{{ $key_value }};
{{ else }}
proxy_pass http://blue;
{{ end }}
{{ end }}
proxy_set_header Host $host;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_http_version 1.1;
}
}
3 changes: 3 additions & 0 deletions nginx/nginx.service
@@ -0,0 +1,3 @@
#!/bin/sh

/usr/sbin/nginx -t && exec /usr/sbin/nginx -g "daemon off;"
26 changes: 26 additions & 0 deletions rollback.sh
@@ -0,0 +1,26 @@
#!/usr/bin/env bash

set -e

kv=http://localhost:8500/v1/kv/deploy/backend

docker exec nginx true 2>/dev/null || docker-compose up -d

echo 'Set previous container as latest'
docker tag app:previous app:latest
docker tag app:previous app:new

echo 'Update green container'
docker-compose up -d green

echo 'Set green container as working'
curl -X PUT -d 'green' ${kv}

echo 'Update blue container'
docker-compose up -d blue

echo 'Set blue container as working'
curl -X PUT -d 'blue' ${kv}

echo 'Stop green container'
docker-compose stop green
14 changes: 14 additions & 0 deletions test.py
@@ -0,0 +1,14 @@
import httplib


def get_status_code(host, path="/"):
try:
conn = httplib.HTTPConnection(host)
conn.request("HEAD", path)
return conn.getresponse().status
except StandardError:
return None


while True:
print get_status_code('localhost')

0 comments on commit ce62b0a

Please sign in to comment.