First version
This commit is contained in:
commit
e3e32d4046
|
@ -0,0 +1,25 @@
|
||||||
|
FROM python:3-alpine
|
||||||
|
|
||||||
|
RUN apk --update add git nginx && \
|
||||||
|
rm /var/cache/apk/*
|
||||||
|
|
||||||
|
RUN pip install requests --no-cache-dir
|
||||||
|
|
||||||
|
RUN mkdir /hook
|
||||||
|
RUN mkdir -p /var/www/html
|
||||||
|
|
||||||
|
# Configure nginx
|
||||||
|
RUN mkdir /run/nginx
|
||||||
|
RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/mkdocs-server.conf
|
||||||
|
RUN rm /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
COPY ./entrypoint.sh /hook
|
||||||
|
COPY ./docker-hook /hook
|
||||||
|
COPY ./update.sh /hook
|
||||||
|
|
||||||
|
WORKDIR /var/www/html
|
||||||
|
|
||||||
|
ENTRYPOINT ["/hook/entrypoint.sh"]
|
||||||
|
|
||||||
|
EXPOSE 80
|
|
@ -0,0 +1,66 @@
|
||||||
|
# Serveur Nginx statique auto-mis à jour via Git
|
||||||
|
|
||||||
|
Cette image Docker permet la mise en place d'un serveur Nginx dont les sources sont un
|
||||||
|
site statique.
|
||||||
|
|
||||||
|
Cependant, cette image offre l'avantage de mettre à jour automatiquement le site dès lors
|
||||||
|
que la branche `master` du dépôt Git est modifiée.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
On désignera par `www.exemple.com` le site sur lequel vous souhaitez héberger votre site.
|
||||||
|
Sur votre dépôt Git, ajoutez un nouveau webhook déclenché à chaque événement `push`
|
||||||
|
(cela suffit normalement) vers l'adresse `https://www.exemple.com/trigger-ci.json`.
|
||||||
|
|
||||||
|
Il vous suffit ensuite de lancer l'image Docker en renseignant la variable d'environnement
|
||||||
|
`MKDOCS_SERVER_GIT_URL` par l'adresse de clonage **HTTPS** du dépôt Git. Par exemple, pour
|
||||||
|
ce dépôt, il s'agit de l'adresse `https://gitlab.com/animath/si/mkdocs-server-from-git.git`.
|
||||||
|
|
||||||
|
Un exemple :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -e NGINX_SERVER_GIT_URL=https://gitlab.com/me/mon-super-projet-nginx.git -p 8000:80 ynerant/nginx-server-from-git
|
||||||
|
```
|
||||||
|
|
||||||
|
Le résultat s'observe sur `http://localhost:8000`.
|
||||||
|
|
||||||
|
Il est recommandé d'utiliser `docker-compose` :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
nginx-static-server:
|
||||||
|
image: ynerant/nginx-server-from-git
|
||||||
|
ports:
|
||||||
|
- 8000:80
|
||||||
|
environment:
|
||||||
|
- NGINX_SERVER_GIT_URL=https://gitlab.com/me/mon-super-projet.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Si vous utilisez Traefik comme reverse-proxy :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
nginx-static-server:
|
||||||
|
image: ynerant/nginx-server-from-git
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
- NGINX_SERVER_GIT_URL=https://gitlab.com/me/mon-super-projet.git
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.nginx-static-server.rule=Host(`www.exemple.com`)"
|
||||||
|
- "traefik.http.routers.nginx-static-server.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.nginx-static-server.tls.certresolver=mytlschallenge"
|
||||||
|
```
|
||||||
|
|
||||||
|
À vous bien sûr d'adapter la configuration comme bon vous semble.
|
||||||
|
|
||||||
|
Enjoy :)
|
||||||
|
|
||||||
|
## Fonctionnement
|
||||||
|
|
||||||
|
L'image contient un serveur Nginx avec deux entrées : un serveur classique desservant
|
||||||
|
le dossier `/var/www/html` et une entrée écoutant sur `/trigger-ci.json` écrite en Python
|
||||||
|
afin de récupérer l'événement de `push` envoyé par le serveur Git.
|
||||||
|
|
||||||
|
À chaque push, le script `update.sh` est exécuté, visant simplement à effectuer un
|
||||||
|
`git pull` afin de mettre à jour les fichiers.
|
||||||
|
|
||||||
|
Le dossier `.git` n'est pas desservi pour des raisons de sécurité.
|
|
@ -0,0 +1,104 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""Automatic Docker Deployment via Webhooks."""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from subprocess import Popen
|
||||||
|
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
|
||||||
|
from http.server import HTTPServer
|
||||||
|
from http.server import BaseHTTPRequestHandler
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
import requests
|
||||||
|
|
||||||
|
logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s',
|
||||||
|
level=logging.DEBUG,
|
||||||
|
stream=sys.stdout)
|
||||||
|
|
||||||
|
class RequestHandler(BaseHTTPRequestHandler):
|
||||||
|
"""A POST request handler which expects a token in its path."""
|
||||||
|
|
||||||
|
def do_POST(self):
|
||||||
|
try:
|
||||||
|
logging.info("Path: %s", self.path)
|
||||||
|
header_length = int(self.headers.get('content-length', "0"))
|
||||||
|
json_payload = self.rfile.read(header_length)
|
||||||
|
env = dict(os.environ)
|
||||||
|
json_params = {}
|
||||||
|
if len(json_payload) > 0:
|
||||||
|
json_params = json.loads(json_payload)
|
||||||
|
env.update(('REPOSITORY_' + var.upper(), str(val))
|
||||||
|
for var, val in json_params['repository'].items())
|
||||||
|
|
||||||
|
logging.info("Start executing '%s'" % args.cmd)
|
||||||
|
try:
|
||||||
|
Popen(args.cmd, env=env).wait()
|
||||||
|
self.send_response(200, "OK")
|
||||||
|
if 'callback_url' in json_params:
|
||||||
|
# Make a callback to Docker Hub
|
||||||
|
data = {'state': 'success'}
|
||||||
|
headers = {'Content-type': 'application/json',
|
||||||
|
'Accept': 'text/plain'}
|
||||||
|
requests.post(json_params['callback_url'],
|
||||||
|
data=json.dumps(data),
|
||||||
|
headers=headers)
|
||||||
|
except OSError as err:
|
||||||
|
self.send_response(500, "OSError")
|
||||||
|
logging.error("You probably didn't use 'sh ./script.sh'.")
|
||||||
|
logging.error(err)
|
||||||
|
if 'callback_url' in json_params:
|
||||||
|
# Make a callback to Docker Hub
|
||||||
|
data = {'state': 'failure',
|
||||||
|
'description': str(err)}
|
||||||
|
headers = {'Content-type': 'application/json',
|
||||||
|
'Accept': 'text/plain'}
|
||||||
|
requests.post(json_params['callback_url'],
|
||||||
|
data=json.dumps(data),
|
||||||
|
headers=headers)
|
||||||
|
self.end_headers()
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
|
|
||||||
|
|
||||||
|
def get_parser():
|
||||||
|
"""Get a command line parser for docker-hook."""
|
||||||
|
parser = ArgumentParser(description=__doc__,
|
||||||
|
formatter_class=ArgumentDefaultsHelpFormatter)
|
||||||
|
|
||||||
|
parser.add_argument("-t", "--token",
|
||||||
|
dest="token",
|
||||||
|
required=False,
|
||||||
|
help=("Secure auth token (can be choosen "
|
||||||
|
"arbitrarily)"))
|
||||||
|
parser.add_argument("-c", "--cmd",
|
||||||
|
dest="cmd",
|
||||||
|
required=True,
|
||||||
|
nargs="*",
|
||||||
|
help="Command to execute when triggered")
|
||||||
|
parser.add_argument("--addr",
|
||||||
|
dest="addr",
|
||||||
|
default="0.0.0.0",
|
||||||
|
help="address where it listens")
|
||||||
|
parser.add_argument("--port",
|
||||||
|
dest="port",
|
||||||
|
type=int,
|
||||||
|
default=8555,
|
||||||
|
metavar="PORT",
|
||||||
|
help="port where it listens")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def main(addr, port):
|
||||||
|
"""Start a HTTPServer which waits for requests."""
|
||||||
|
httpd = HTTPServer((addr, port), RequestHandler)
|
||||||
|
httpd.serve_forever()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = get_parser()
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
parser.print_help()
|
||||||
|
sys.exit(1)
|
||||||
|
args = parser.parse_args()
|
||||||
|
main(args.addr, args.port)
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cd /var/www/html
|
||||||
|
[ -d .git ] || git clone ${NGINX_SERVER_GIT_URL} .
|
||||||
|
|
||||||
|
git pull
|
||||||
|
nginx&
|
||||||
|
python /hook/docker-hook -c sh /hook/update.sh
|
|
@ -0,0 +1,25 @@
|
||||||
|
upstream trigger-ci {
|
||||||
|
server 127.0.0.1:8555;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name static-server;
|
||||||
|
root /var/www/html;
|
||||||
|
error_page 404 /404.html;
|
||||||
|
|
||||||
|
location /trigger-ci.json {
|
||||||
|
proxy_pass http://trigger-ci;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_redirect off;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /.git* {
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /README* {
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue