Makefile
Nous utilisons un fichier Makefile pour organiser les scripts qui seront appelés dans les étapes de la CI.
Il regroupe les commandes nécessaires à la construction de l’application, et qui seront jouées dans le scénario décrit dans le fichier .gitlab-ci.yml
, et ainsi reproduites sur le serveur d’intégration.
Préparation
La récupération de la dernière version des images de base est nécessaire pour s’assurer que le build de l’application utilisera une version à jour des images de base Docker. En utilisant les outils propres aux langages du projet, la CI va télécharger les bibliothèques nécessaires. Il peut être judicieux d’utiliser les volumes et le système de cache proposé par la CI pour diminuer le temps requis par certaines étapes du pipeline.
pull:
# pull latest images required for our build
docker pull bearstech/python:3
docker pull bearstech/python-dev:3
Etape de build
La construction de l’image de notre application se fait au sein de cette étape préalable aux autres:
# current user id is usefull to be able to write in volumes
export UID:=$(shell id -u)
build:
# build the docker images with the commit as tag
docker build -t $(CI_REGISTRY_IMAGE)/app:$(CI_COMMIT_SHA) \
-f Dockerfile --build-arg=uid=$(UID) .
Ici, on vient spécifier l’uid (celui de l’utilisateur courant) qui sera utilisé pour instancier l’application tel que définit dans le Dockerfile. On remarque aussi que la commande docker build
utilise les variables d’environnement de Gitlab CI afin de taguer l’image.
Pousser l’image sur la registry
Une fois l’image de l’application construite, elle doit être disponible sur la registry privée de Gitlab:
push:
# push images to our private registry
docker push $(CI_REGISTRY_IMAGE)/app:$(CI_COMMIT_SHA)
Instancier l’application
Les directives qui permettent d’instancier l’application sont utiles pour lancer l’application en local, mais aussi pour réaliser des tests unitaires ou fonctionnels sur le serveur de CI:
up:
# run compose in background
docker-compose up -d
# wait for services using the bearstech/traefik-dev container utils
docker-compose exec -T traefik wait_for_services -v --timeout 20
# show apps logs
docker-compose logs --tail="all" app
Le Makefile
utilisé pour faire fonctionner le workflow regroupe les commandes nécessaires aux étapes de la CI:
- Le build de l’image garantit la mise à jour des librairies et des briques du système qui seront embarqués dans les conteneurs.
- Le push sur la registry dépend du commit, et ainsi il est toujours possible de retrouver l’état de l’application au moment du build.
- Le développeur peut travailler sur l’application dans un environnement similaire à celui de la production
Voici le Makefile
qui sera utilisé pour réaliser l’intégration de l’application écrite en python:
# The Makefile defines all builds steps
# current user id is usefull to be able to write in volumes
export UID:=$(shell id -u)
# compose command to merge production file and and dev/tools overrides
COMPOSE?=docker-compose -f docker-compose.yml -f tools.yml -f dev.yml
# docker run command used to build dependencies before images build
DOCKER?=docker run --rm -u $(UID) -e "HOME=/home/myapp" -w "/home/myapp" \
-v "$(PWD):/home/myapp" -v "$(HOME)/.cache:/.cache" \
bearstech/python-dev:3
export COMPOSE DOCKER
# Define some defaults if we are not on CI
TRAEFIK_HTTP_PORT?=80
TRAEFIK_UI_PORT?=8080
# Let compose be aware of some vars
export TRAEFIK_HTTP_PORT TRAEFIK_UI_PORT
# this is usefull with most python apps in dev mode because if stdout is
# buffered logs do not shows in realtime
PYTHONUNBUFFERED=1
export PYTHONUNBUFFERED
pull:
# pull latest images required for our build
docker pull bearstech/python:3
docker pull bearstech/python-dev:3
$(HOME)/.cache:
mkdir -p $(HOME)/.cache
venv: $(HOME)/.cache
# install some software with a dev image here
$(DOCKER) python3 -m venv venv
$(DOCKER) venv/bin/pip install -U pip wheel
$(DOCKER) venv/bin/pip install -U -r requirements.txt
build: venv
# build the docker images with the commit as tag
docker build -t $(CI_REGISTRY_IMAGE)/app:$(CI_COMMIT_SHA) \
-f Dockerfile.app --build-arg=uid=$(UID) .
push:
# push images to our private registry
docker push $(CI_REGISTRY_IMAGE)/app:$(CI_COMMIT_SHA)
data/uploads:
# initialize some dirs. do not let docker create them with uid root
mkdir -p data/uploads
volumes: data/uploads
up: volumes
# run compose in background
$(COMPOSE) up -d
# wait for services using the bearstech/traefik-dev container utils
$(COMPOSE) exec -T traefik wait_for_services -v --timeout 20
# show apps logs
$(COMPOSE) logs --tail="all" app
dev: volumes
# run compose in foreground
$(COMPOSE) up app
down:
# stop compose
$(COMPOSE) down --remove-orphans