Docker Dockerfile et API

Le fichier Dockerfile définit ce qui se passe dans à l’intérieur du conteneur comme l’accès aux ressources (interfaces réseau, lecteurs de disque) qui seront virtualisées dans cet environnement isolé du reste du système. Parfois les Dockerfiles font appel à des fichiers annexes pour construire le projet.

Le fichier Dockerfile

Le fichier Dockerfile doit être positionné à la racine de votre projet, ici le répertoire Projet/.

# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /Projet
WORKDIR /Projet

# Copy the current directory contents into the container at /Projet
COPY . /Projet

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

Ce fichier Dockerfile fait référence à quelques fichiers que nous n’avons pas encore créés, à savoir app.py et Requirements.txt.

Création de l’API

Nous allons créer les fichiers Requirements.txt et app.py dans la racine du projet au même niveau que le Dockerfile.
Lorsque le fichier Dockerfile sera appelé depuis le lancement d’une image les fichiers app.py et Requirements.txt sont présents dans le container en raison de la commande COPY. Le résultat du fichier app.py est accessible via HTTP grâce à la commande EXPOSE.

requirements.txt

Flask
Redis

app.py

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)
requirelme
@app.route("/")
def hello():
try:
visits = redis.incr("counter")
except RedisError:
visits = "<i>cannot connect to Redis, counter disabled</i>"

html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>" \
"<b>Visits:</b> {visits}"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)

Nous voyons maintenant que pip install -r requirements.txt installe les bibliothèques Flask et Redis pour Python et que l’application imprime la variable d’environnement NAME, ainsi que la sortie d’un appel à socket.gethostname(). Enfin, étant donné que Redis n’est pas en cours d’exécution (nous n’avons installé que la bibliothèque Python, et non Redis elle-même), nous devons nous attendre à ce que la tentative de l’utiliser ici échoue et génère le message d’erreur.

Remarque : l’accès au nom de l’hôte à l’intérieur d’un conteneur extrait l’ID de conteneur, qui est similaire à l’ID de processus d’un exécutable en cours d’exécution.

Construire l’application app

Création de l’image que nous allons appeler MyImageDock:v0.0.1. à l’aide de l’option –-tag ou -t. (Ne pas oublier le point “.” à la fin).

docker build --tag=MyImageDock:v0.0.1. .

Lister les images précédemment construites :

$ docker image ls // ou $ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
MyImageDock:v0.0.1. latest 2e476f1acc2d 27 hours ago 131MB

Lancer le projet

Lancer le container en mappant le port 4000 de votre machine sur le port 80 du conteneur à l’aide de -p :

$ docker run -p 4000:80 MyImageDock:v0.0.1.

Vous devriez voir un message indiquant que Python sert votre application à l’adresse http://0.0.0.0:80. Mais ce message provient de l’intérieur du conteneur qui ne sait pas que vous avez mappé le port 80 de ce conteneur sur 4000. L’URL correcte est http://localhost:4000.

Accédez à cette URL dans un navigateur Web pour voir le contenu d’affichage diffusé sur une page Web.

Le terminal où est lancé Docker renvoie ceci :

 * Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
195.181.167.150 - - [25/Jan/2019 15:37:44] "GET / HTTP/1.1" 200 -
195.181.167.150 - - [25/Jan/2019 15:37:44] "GET /favicon.ico HTTP/1.1" 404 -
195.181.167.150 - - [25/Jan/2019 15:37:56] "GET / HTTP/1.1" 200 -

Il est également possible d’utiliser la commande curl :

$ curl http://@ipServ:4000

<h3>Hello World!</h3><b>Hostname:</b> 8fc990912a14<br/>
<b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>

Autre exemple de projet avec Dockerfiles

In a nutshell :

  • RUN Exécute la commande et créer une nouvelle image, utilisé par exemple pour installer des packages.
  • CMD Définit la commande ou les paramètres par défaut.
  • ENTRYPOINT Configure un container qui peut être lancé comme un exécutable.

Dans un dossier nommé /Projet :

# ls -la Projet/
total 36
drwxr-xr-x 2 root root 4096 Jun 2 06:55 .
drwx------ 7 root root 4096 Jun 2 07:04 ..
-rw-r--r-- 1 root root 1349 Jun 1 16:04 .bashrc
-rw-r--r-- 1 root root 1101 Jun 2 06:55 Dockerfile
-rw-r--r-- 1 root root 85 Jun 1 09:25 .dockerignore
-rw-r--r-- 1 root root 85 Jun 1 09:26 README.md

Contenu de Dockerfile :

#
# Ce Dockerfile permet de créer un serveur debian avec Nginx + php
#
# Version 0.0.1
#

# Image
FROM debian:stable

MAINTAINER OPM Saitama [email protected]

RUN apt-get update && apt-get upgrade -y && apt-get install -y \
vim \
nginx \
php-fpm \
php-mysql

# PORT Ouverture des ports 22, 80
EXPOSE 80 22

# Copie du .bashrc déjà customisé vers le container.
ADD .bashrc /root/.bashrc

# Test FONCTIONNE BIEN
RUN echo "test RUN dans txt" > fichier1.txt

# ****************************
# RUN et CMD ne marche pas ensuite...
RUN echo "test RUN"
RUN cd /root
RUN service nginx start
RUN service php7.0-fpm start

ENV image "Image Docker pour Nginx et php7"
CMD ["echo -e \n\e[0;33m Bonjour, bienvenu sur votre $image !"]
CMD ["echo test CMD"]
CMD ["echo test CMD dans txt"] > fichier2.txt

Lancer le dockerfile dans le dossier courant (ne pas oublier le ‘.’ à la fin) pour créer une image.

# docker build -t test.dockerfile .

Puis créer et lancer un container à partir de cette image :

# docker run -it --name="dockerfile.container" test.dockerfile /bin/bash

Documentation

https://docs.docker.com/get-started/part2/
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)
https://journaldunadminlinux.fr/tuto-docker-demarrer-avec-docker/#comment-3630)
https://www.digitalocean.com/community/tutorials/docker-explained-using-dockerfiles-to-automate-building-of-images
http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/

> Partager <