Skip to content
Snippets Groups Projects
Commit 770e1e4b authored by Bot's avatar Bot Committed by TakiBot
Browse files

Added solution for 01-docker

parent d45e8587
Branches main
No related tags found
No related merge requests found
Pipeline #53153 passed
Showing
with 1091 additions and 0 deletions
# TP part 01 - Docker
## Introduction
L'objectif de ce TP est de prendre en main l'environnement Docker et plus si affinitée !
Le but de ce TP est de créer trois conteneurs :
- Un serveur Web : Apache
- Un serveur backend avec une API : Java
- Une base de données : PostgreSQL
- Un client pour la base de données : adminer (Optionnel)
Les notions suivantes seront abordées :
- Création d'un image personalisée avec Dockerfile
- L'exposition des ports d'un container
- Le mappage des ports d'un container
- Le mappage de volume pour bénéficier de la persistance
- L'utilisation d'entrypoint (mis à disposition par l'image)
- L'utilisation de docker-compose
- La configuration très basique d'un reverse proxy
## Base de donnée
### Build de l'image
On build notre image :
```docker
docker build -t database .
```
* ```-t database``` : permet de spécifier un tag à l'image
* ```.``` : spécifie le contexte
* ```-f Database.Dockerfile``` : permet de spécifier le nom du Dockerfile si le nom par défaut n'est pas utilisé
### Lancement d'un conteneur
Ensuite on run / exécute notre image :
```docker
docker run --rm \
--name database \
--env-file .env \
# -p 5432:5432 \ Facultatif -> Utile si on souhaite exposer la BDD, dans notre cas non --> seulement à d'autre conteneur présent sur la même machine --> la solution : utilisé le nom du contenur directement !
--network=bridge-app-network \
database
```
Il faut avoir au préalable crée le network -> ```docker network create app-network```
Explication des paramètres :
* ```--rm``` : effectue un clean-up du container quand il est arrêté.
* Càd : Docker supprime automatiquement le container (et tout ce qui est lié à celui-ci) quand il est arrêté et les volumes anonymes associés (équivalent de ```docker rm -v database```).
* A noter : Pas utilisé en prod mais pratique pour tester/accomplir quelque chose dans un temps réduit -> tester, compiler une application au sein d'un conteneur, vérifier un bon fonctionnement et libérer de l'espace une fois fini.
* ```--name``` : permet de nommer le container pour l'identifier, par ex : utiliser son nom pour le lier à d'autres applications.
* ```-env-file``` : permet de spécifier le fichier qui contient les variables d'environnment.
* A noter : on peut aussi spécifier directement des variables d'environement avec ```-e VAR1=TOTO``` (alias de ```-env```) mais cela devient fastidieux si l'on a beaucoup de variables d'environnement.
* ```-p``` : permet de mapper un ou plusieurs port de la machine hôte avec le conteneur
* ```-v``` : permet de mapper un ou plusieurs volume de la machine hôte avec le conteneur (pour bénéficier de données persistante -> la base de données ne sera pas vide à chaque redémarrage).
Ajouter adminer (facultatif) :
```
docker run --network=app-network -p 8081:8080 adminer
```
## Application Java
## Build de l'image
On build notre image :
```docker
docker build -t backend .
```
On lance le container:
```
docker run --network=app-network -p 8080:8080 --name backend_app backend
```
## Reverse-Proxy
On fait exactement la même chose que pour les étapes d'avant on build et on run l'image d'un proxy httpd
puis récuperer sa conf avec la commande suivante:
```docker exec -it your_running_container cat /usr/local/apache2/conf/httpd.conf > httpd.conf```
# Docker-Compose pour les rassembler tous !
Docker-Compose est un super outil pour configurer/définir/désigner des applications docker avec plusieurs conteneurs.
Celui-ci est au format YAML.
* Voici la documentation : https://docs.docker.com/compose/
Pour créer et lancer les conteneurs : ```docker-compose up``` et ajouter ```-d``` pour lancer en arrière plan
Pour arrêter et supprimer l'ensemble des éléments (volumes, netorks, containers, images) : ```docker-compose down```
version: '3'
services:
webapp:
image: registry.takima.io/school/proxy/nginx
ports:
- "8082:80"
networks:
- my-network
volumes:
- my-volume:/app/data
environment:
- DATABASE_URL=mysql://dbuser:dbpassword@db/dbname
db:
image: mysql:5.7
networks:
- my-network
environment:
- MYSQL_ROOT_PASSWORD=rootpassword
- MYSQL_DATABASE=dbname
- MYSQL_USER=dbuser
- MYSQL_PASSWORD=dbpassword
volumes:
- db-data:/var/lib/mysql
networks:
my-network:
driver: bridge
volumes:
my-volume:
db-data:
\ No newline at end of file
# notre image de base
FROM alpine:3.6
# Installer Python et pip
RUN apk add --update py2-pip
# Installer les modules Python nécessaires par l'application Python
COPY requirements.txt /usr/src/app/
RUN pip install --no-cache-dir -r /usr/src/app/requirements.txt
# Copier les fichiers nécessaires pour l'exécution de l'application
COPY app.py /usr/src/app/
COPY templates/index.html /usr/src/app/templates/
# Indiquer le numéro de port que le conteneur doit exposer
EXPOSE 5000
# Exécuter l'application
ENTRYPOINT ["python", "/usr/src/app/app.py"]
\ No newline at end of file
from flask import Flask, render_template
import random
app = Flask(__name__)
# liste des images
images = [
"https://c.tenor.com/GTcT7HODLRgAAAAM/smiling-cat-creepy-cat.gif",
"https://media0.giphy.com/media/10dU7AN7xsi1I4/giphy.webp?cid=ecf05e47gk63rd81vzlot57qmebr7drtgf6a3khmzvjsdtu7&rid=giphy.webp&ct=g",
"https://media0.giphy.com/media/S6VGjvmFRu5Qk/giphy.webp?cid=ecf05e478yofpawrhffnnvb3sgjkos96vyfo5mtqhds35as6&rid=giphy.webp&ct=g",
"https://media3.giphy.com/media/JIX9t2j0ZTN9S/200w.webp?cid=ecf05e47gk63rd81vzlot57qmebr7drtgf6a3khmzvjsdtu7&rid=200w.webp&ct=g"
]
@app.route('/')
def index():
url = random.choice(images)
return render_template('index.html', url=url)
if __name__ == "__main__":
app.run(host="0.0.0.0")
Flask==0.10.1
\ No newline at end of file
<html>
<head>
<style type="text/css">
body {
background: black;
color: white;
}
div.container {
max-width: 500px;
margin: 100px auto;
border: 20px solid white;
padding: 10px;
text-align: center;
}
h4 {
text-transform: uppercase;
}
</style>
</head>
<body>
<div class="container">
<h4>Cat Gif of the day</h4>
<img src="{{url}}" />
<p>
<small
>Courtesy:
<a
href="http://www.buzzfeed.com/copyranter/the-best-cat-gif-post-in-the-history-of-cat-gifs"
>Buzzfeed</a
></small
>
</p>
</div>
</body>
</html>
\ No newline at end of file
POSTGRES_PASSWORD=pwd
POSTGRES_USER=usr
POSTGRES_DB=db
\ No newline at end of file
FROM registry.takima.io/school/proxy/postgres:14.1-alpine
COPY ./scripts/ /docker-entrypoint-initdb.d
CREATE TABLE public.departments
(
id SERIAL PRIMARY KEY,
name VARCHAR(20) NOT NULL
);
CREATE TABLE public.students
(
id SERIAL PRIMARY KEY,
department_id INT NOT NULL REFERENCES departments (id),
first_name VARCHAR(20) NOT NULL,
last_name VARCHAR(20) NOT NULL
);
INSERT INTO departments (name) VALUES ('IRC');
INSERT INTO departments (name) VALUES ('ETI');
INSERT INTO departments (name) VALUES ('CGP');
INSERT INTO students (department_id, first_name, last_name) VALUES (1, 'Eli', 'Copter');
INSERT INTO students (department_id, first_name, last_name) VALUES (2, 'Emma', 'Carena');
INSERT INTO students (department_id, first_name, last_name) VALUES (2, 'Jack', 'Uzzi');
INSERT INTO students (department_id, first_name, last_name) VALUES (3, 'Aude', 'Javel');
version: '3.3'
services:
backend:
container_name: backend
build: ./simple-api
networks:
- back-network
- front-network
depends_on:
database:
condition: service_healthy
env_file:
- simple-api/.env
database:
container_name: database
restart: always
build: ./database
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 3
networks:
- back-network
env_file:
- database/.env
httpd:
container_name: reverse_proxy
build: ./httpd
ports:
- "80:80"
networks:
- front-network
volumes:
my_db_volume:
driver: local
networks:
back-network:
front-network:
version: '3.3'
services:
backend:
container_name: backend
build: ./simple-api
networks:
- back-network
- front-network
depends_on:
- database
env_file:
- simple-api/.env
database:
container_name: database
restart: always
build: ./database
networks:
- back-network
env_file:
- database/.env
httpd:
container_name: reverse_proxy
build: ./httpd
ports:
- "80:80"
networks:
- front-network
volumes:
my_db_volume:
driver: local
networks:
back-network:
front-network:
version: '3.3'
services:
backend:
container_name: backend
build: ./simple-api
networks:
- app-network
depends_on:
- database
env_file:
- simple-api/.env
database:
container_name: database
restart: always
build: ./database
networks:
- app-network
env_file:
- database/.env
httpd:
container_name: reverse_proxy
build: ./httpd
ports:
- "80:80"
networks:
- app-network
volumes:
my_db_volume:
driver: local
networks:
app-network:
FROM registry.takima.io/school/proxy/httpd:2.4
COPY ./httpd.conf /usr/local/apache2/conf/httpd.conf
EXPOSE 80
CMD ["httpd", "-D", "FOREGROUND"]
This diff is collapsed.
POSTGRES_PASSWORD=pwd
POSTGRES_USER=usr
POSTGRES_DB=db
POSTGRES_URL=database
POSTGRES_PORT=5432
\ No newline at end of file
# Build
FROM registry.takima.io/school/proxy/maven:3.8.5-openjdk-17-slim AS myapp-build
ENV MYAPP_HOME /opt/myapp
WORKDIR $MYAPP_HOME
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
# Run
FROM registry.takima.io/school/proxy/openjdk:17-slim
ENV MYAPP_HOME /opt/myapp
WORKDIR $MYAPP_HOME
COPY --from=myapp-build $MYAPP_HOME/target/*.jar $MYAPP_HOME/myapp.jar
EXPOSE 8080
ENTRYPOINT java -jar myapp.jar
# Read Me First
The following was discovered as part of building this project:
* The original package name 'fr.takima.training.simple-api' is invalid and this project uses 'fr.takima.training.simpleapi' instead.
# Getting Started
### Reference Documentation
For further reference, please consider the following sections:
* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.4.RELEASE/maven-plugin/)
* [Spring Web](https://docs.spring.io/spring-boot/docs/2.2.4.RELEASE/reference/htmlsingle/#boot-features-developing-web-applications)
* [Spring Data JPA](https://docs.spring.io/spring-boot/docs/2.2.4.RELEASE/reference/htmlsingle/#boot-features-jpa-and-spring-data)
### Guides
The following guides illustrate how to use some features concretely:
* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/)
* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/)
* [Building REST services with Spring](https://spring.io/guides/tutorials/bookmarks/)
* [Accessing Data with JPA](https://spring.io/guides/gs/accessing-data-jpa/)
* [Accessing data with MySQL](https://spring.io/guides/gs/accessing-data-mysql/)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>fr.takima.training</groupId>
<artifactId>simple-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>simple-api</name>
<description>Simple API demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
<jacoco-maven-plugin.version>0.8.8</jacoco-maven-plugin.version>
<testcontainers.version>1.17.4</testcontainers.version>
<validation.version>2.0.1.Final</validation.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>jdbc</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>${validation.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
<configuration>
<append>true</append>
</configuration>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package fr.takima.training.simpleapi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SimpleApiApplication {
public static void main(String[] args) {
SpringApplication.run(SimpleApiApplication.class, args);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment