This project provides a Docker setup for a PostgreSQL database along with Adminer for database management. Below are the detailed steps to create and manage your PostgreSQL Docker container, set up networking, and ensure data persistence.
- Docker installed on your machine
- Terminal or command prompt access
Create a Dockerfile with the following content:
FROM postgres:14.1-alpine
ENV POSTGRES_DB=db \
POSTGRES_USER=usr \
POSTGRES_PASSWORD=pwdOpen a terminal and navigate to the directory containing your Dockerfile. Run the following command to build the Docker image:
docker build -t my_postgres .This command will build the image and tag it as my_postgres.
Create a Docker network named app-network:
docker network create app-networkRun a container from the image you just built. Use the following command to start the container and bind a port on your host to the container's port 5432:
docker run --name myPostgres -p 5432:5432 -d --network app-network my_postgresTo verify that the container is running, use:
docker psYou should see output similar to this:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0e69fce54a49 my_postgres "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:5432->5432/tcp myPostgres
Run an Adminer container for database management:
docker run --name my_adminer -p 8080:8080 --network app-network -d adminerYou can now access Adminer by navigating to http://localhost:8080 in your web browser.
Create a directory named data in the same location as your Dockerfile. Place your SQL files inside this data directory.
01-CreateScheme.sql:
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 );
02-InsertData.sql :
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');
put sql files in /docker-entrypoint-initdb.d on docker; When rerun, it deletes the files because they are not permanent.
To persist data and ensure it is not lost when the container is removed, use volumes. This will map a directory on your host machine to the container:
docker run --name myPostgres -d --network app-network -v ./data:/docker-entrypoint-initdb.d my_postgresEnsure your SQL files are located in the ./data directory on your host. These files will be copied to the container's /docker-entrypoint-initdb.d directory when the container starts. You can verify this by checking the contents of the directory within the container.
If you need to make changes to the SQL files and want them to be reloaded, remove the existing container and recreate it:
docker rm -f mypostgres
docker run --name mypostgres -d --network app-network -v ./data:/docker-entrypoint-initdb.d my_postgresEnsure your Dockerfile includes the instruction to copy the SQL files:
FROM postgres:14.1-alpine
# Copy the SQL scripts into the container
COPY ./data /docker-entrypoint-initdb.d
ENV POSTGRES_DB=db \
POSTGRES_USER=usr \
POSTGRES_PASSWORD=pwdEnsure your SQL files are correctly added to the entrypoint directory /docker-entrypoint-initdb.d. This ensures they are executed when the container is started.
After recreating the container, verify that the SQL files have been correctly copied into the container and are persistent across container restarts. You can check the container's /docker-entrypoint-initdb.d directory.
You now have a PostgreSQL database running in a Docker container, connected to an Adminer interface for easy database management. The use of Docker volumes ensures that your data persists across container restarts and recreations.
1. Création du fichier Main.java:
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}2. Compilation avec la version Java cible: javac Main.java.
Comme Java n'est pas installé sur mon ordinateur je n'ai pas pu éxecuter la commande javac pour compiler mon fichier java. Ce qui rend encore plus compréhensible l'utilisation d'un docker pour utiliser java.
3. Création du Dockerfile:
# Utilisation d'une image Java pour exécuter un environnement Java runtime
FROM openjdk:17-rc-oraclelinux8
# Création d'un répertoire de travail
WORKDIR /app
# Copie du fichier .class compilé dans le conteneur
COPY Main.class /app
# Exécution de l'application Java
CMD ["java", "Main"]4. Construction de l'image Docker:
docker build -t java-hello-world .5. Exécution du conteneur Docker:
docker run --name java-hello-world-container --network app-network java-hello-world1. Création d'une application Spring Boot avec Spring Initializr:
Nous avons utilisé Spring Initializr pour générer une nouvelle application Spring Boot avec les dépendances nécessaires pour créer une API Web simple.
2. Implémentation du contrôleur GreetingController:
Nous avons créé une classe GreetingController qui définit un point de terminaison REST simple qui renvoie une salutation avec un paramètre optionnel pour le nom.
package fr.takima.training.simpleapi.controller;
import org.springframework.web.bind.annotation.*;
import java.util.concurrent.atomic.AtomicLong;
@RestController public class GreetingController {
private static final String template = "Hello, %s!"; private final AtomicLong counter = new AtomicLong();
@GetMapping("/") public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) { return new Greeting(counter.incrementAndGet(), String.format(template, name)); }
record Greeting(long id, String content) {}
}
3. Création du Dockerfile pour l'application Spring Boot:
# Étape de construction
FROM maven:3.8.6-amazoncorretto-17 AS myapp-build
ENV MYAPP_HOME /opt/myapp
WORKDIR $MYAPP_HOME
COPY pom.xml .
COPY src ./src
RUN mvn package -DskipTests
# Étape d'exécution
FROM amazoncorretto:17
ENV MYAPP_HOME /opt/myapp
WORKDIR $MYAPP_HOME
COPY --from=myapp-build $MYAPP_HOME/target/*.jar $MYAPP_HOME/myapp.jar
ENTRYPOINT java -jar myapp.jar###1-2 Why do we need a multistage build? And explain each step of this dockerfile. Les constructions multistades dans Docker sont utilisées pour optimiser la taille de l'image Docker finale. Cela implique de définir plusieurs étapes de construction dans un seul Dockerfile, chacune avec son propre ensemble d'instructions et d'environnement. Ces étapes permettent de séparer différentes phases du processus de construction d'une application, telles que la compilation du code, l'exécution des tests et l'emballage de l'application, en étapes distinctes. Chaque étape peut partir d'une image de base différente et copier uniquement les fichiers nécessaires des étapes précédentes, réduisant ainsi la taille de l'image finale en excluant les dépendances de construction et les artefacts inutiles.
Explication: Dans ce DockerFile, la première étape utilise une image Maven pour construire l'application Java, puis la deuxième étape utilise une image Amazon Corretto JDK pour exécuter l'application, en copiant le fichier JAR généré à partir de l'étape précédente.
4. Construction de l'image Docker:
docker build -f Dockerfile -t simpleapi .5. Exécution du conteneur Docker:
docker run -p 80:8080 simpleapi1. Ajustement de la configuration dans simple-api/src/main/resources/application.yml:
Nous avons ajusté le fichier application.yml pour configurer la connexion à la base de données. Nous avons fourni l'URL, le nom d'utilisateur et le mot de passe pour se connecter à la base de données PostgreSQL.
2. Exécution du conteneur Docker:
Nous avons exécuté le conteneur Docker avec les modifications apportées à la configuration pour nous assurer que l'application est correctement liée à la base de données. Une fois que tout est correctement lié, nous devrions pouvoir accéder à notre API d'application, par exemple sur : /departments/IRC/students.
[
{
"id": 1,
"firstname": "Eli",
"lastname": "Copter",
"department": {
"id": 1,
"name": "IRC"
}
}
]1. Choose an appropriate base image:
Nous avons commencé par sélectionner une image de base appropriée pour notre serveur HTTP. Dans ce cas, nous avons utilisé l'image httpd:2.4-alpine, qui fournit un serveur HTTP Apache.
2. Create a simple landing page: index.html
Nous avons créee une pages html basique appelé index.html et l'avons placé à l'intérieur de notre conteneur. Voici le contenu de la page html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome to My Httpd Docker Container!</title>
</head>
<body>
<header>
<h1>Welcome to My Httpd Docker Container!</h1>
</header>
<main>
<p>This is a simple landing page served by the Httpd (Apache) server inside a Docker container.</p>
</main>
</body>
</html>3. Dockerfile:
FROM httpd:2.4-alpine
COPY index.html /usr/local/apache2/htdocs/4. Build the Docker image:
docker build -t my-httpd-image .5. Run the container:
docker run --name my-httpd-container -p 82:80 -d my-httpd-image6. Verify everything is working:
You can check that everything is working as expected using the following commands:
docker stats
docker inspect my-httpd-container
docker logs my-httpd-container1. Retrieve the default configuration from the running container:
Nous pouvons utiliser docker exec pour récupérer le fichier de configuration par défaut du conteneur en cours d'exécution dans /usr/local/apache2/conf/httpd.conf.
docker exec -it my-httpd-container cat /usr/local/apache2/conf/httpd.conf2. Modify the default configuration:
Ajoutez la configuration suivante dans /usr/local/apache2/conf/httpd.conf pour activer le proxy inverse :
<VirtualHost *:80>
ProxyPreserveHost On
ProxyPass / http://simple-api-container-student:8080/
ProxyPassReverse / http://simple-api-container-student:8080/
</VirtualHost>
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
3. Update the Dockerfile to include the modified configuration:
COPY httpd.conf /usr/local/apache2/conf/httpd.confUn proxy inverse peut être utile pour plusieurs raisons, notamment
- Servir des applications frontales.
- Configuration de la terminaison SSL.
- Gestion de l'équilibrage de la charge.
Docker-Compose est un outil qui permet de définir et de gérer des applications Docker multi-conteneurs. Il utilise un fichier YAML pour configurer les services, les réseaux et les volumes de l'application. Dans notre cas, nous utilisons Docker-Compose pour orchestrer les conteneurs de l'API dorsale, de la base de données et du serveur HTTP.
1. Install Docker-Compose:
Si la commande docker-compose n'est pas disponible sur votre système, vous devez installer Docker-Compose. Suivez les instructions d'installation fournies dans la documentation Docker pour votre système d'exploitation.
2. Create docker-compose.yml:
Nous avons créé un fichier docker-compose.yml pour définir notre application multi-conteneurs. Voici le contenu de notre configuration Docker-Compose :
version: '3.7'
services:
backend:
build:
context: "C:\\Users\\Clément\\OneDrive - Fondation EPF\\4A\\Devops-main\\backend api\\simple-api-student-main"
container_name: "simple-api-container-student2"
networks:
- app-network
depends_on:
- database
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://mypostgres2:5432/db
- SPRING_DATASOURCE_USERNAME=usr
- SPRING_DATASOURCE_PASSWORD=pwd
- SPRING_JPA_HIBERNATE_DDL_AUTO=update
- SPRING_JPA_DATABASE_PLATFORM=org.hibernate.dialect.PostgreSQLDialect
database:
build:
context: "C:\\Users\\Clément\\OneDrive - Fondation EPF\\4A\\Devops-main\\postgres"
container_name: "mypostgres2"
networks:
- app-network
environment:
- POSTGRES_DB=db
- POSTGRES_USER=usr
- POSTGRES_PASSWORD=pwd
httpd:
build:
context: "C:\\Users\\Clément\\OneDrive - Fondation EPF\\4A\\Devops-main\\http"
ports:
- "82:80"
networks:
- app-network
depends_on:
- backend
- database
networks:
app-network:-
Backend Service:
- Build Context: Specifies the path to the backend API code.
- Container Name: Names the container
simple-api-container-student2. - Networks: Connects to
app-network. - Depends On: Specifies that the backend service depends on the
databaseservice. - Environment Variables: Configures the Spring Boot application to connect to the PostgreSQL database.
-
Database Service:
- Build Context: Specifies the path to the PostgreSQL Dockerfile.
- Container Name: Names the container
mypostgres2. - Networks: Connects to
app-network. - Environment Variables: Sets the database name, user, and password.
-
HTTPD Service:
- Build Context: Specifies the path to the HTTP server configuration.
- Ports: Maps port 82 on the host to port 80 in the container.
- Networks: Connects to
app-network. - Depends On: Specifies that the HTTPD service depends on both
backendanddatabaseservices.
-
Network:
- app-network: Creates a custom network for inter-container communication.
Pour démarrer l'application à l'aide de Docker-Compose, exécutez la commande suivante :
docker-compose upCette commande va construire et démarrer tous les services définis dans le fichier docker-compose.yml.
1. Tag the Image:
Pour cela, nous avons besoin d'un compte dockerhub. Pour publier l'image Docker sur Docker Hub, nous avons d'abord étiqueté l'image avec une version significative :
docker tag devops-database cjassey/my-database:1.0"cjassey" is the account username. "devops-database" is the name of the local Docker image you built earlier with dosker-compose.
2. Push the Image:
Ensuite, nous avons poussé l'image étiquetée vers Docker Hub :
docker push cjassey/my-database:1.0Après avoir poussé l'image, elle est disponible dans le dépôt Docker Hub sous notre compte.
Il est important de fournir de la documentation pour vos images Docker sur Docker Hub. Cette documentation doit inclure des détails sur l'image, des instructions d'utilisation et toute information de configuration pertinente. Cela permet aux membres de l'équipe ou à d'autres personnes d'utiliser plus facilement les images de manière efficace.
Docker-Compose simplifie le processus de gestion des applications multi-conteneurs. Il vous permet de définir, de construire et d'exécuter tous les services à l'aide d'une seule commande, ce qui facilite la gestion des dépendances et des configurations.
La publication d'images Docker dans un référentiel en ligne tel que Docker Hub facilite le partage et la distribution des images. Cela permet aux membres de l'équipe d'extraire et d'exécuter les images sur leurs machines, garantissant ainsi la cohérence entre les différents environnements. Cela facilite également l'intégration continue et les flux de travail de déploiement.
En suivant ces étapes, nous avons réussi à mettre en place et à gérer une application multi-conteneurs à l'aide de Docker-Compose, et à publier nos images Docker sur Docker Hub pour en faciliter la distribution et l'utilisation.
-
Create a New GitHub Repository and Push Your Project:
1.1 Create a New Repository:
- Go to GitHub and create a new repository named
Devops.
1.2 Add Your Project to the Repository:
- Open your terminal and navigate to your project directory.
- Initialize the Git repository if it's not already done:
git init
- Add all your project files to the repository:
git add . - Make an initial commit:
git commit -m "Initial commit" - Add the remote repository:
git remote add origin https://github.com/cjassey/Projet_DevOps.git
- Push your project to the GitHub repository:
git push -u origin main
- Go to GitHub and create a new repository named
Pour créer et tester votre application Java à l'aide de Maven, procédez comme suit :
- Download Maven:
- Allez sur la [page de téléchargement de Maven] (https://maven.apache.org/download.cgi).
- Téléchargez la dernière archive zip binaire (par exemple,
apache-maven-3.9.7-bin.zip).
- Extract Maven:
- Extrayez le fichier zip téléchargé dans un répertoire de votre choix, par exemple,
C:\N-apache-maven-3.9.7.
- Extrayez le fichier zip téléchargé dans un répertoire de votre choix, par exemple,
- Set Up Environment Variables:
- Ajoutez
C:\N-apache-maven-3.9.7\Nbinà la variable d'environnementPATHde votre système :- Ouvrez le Menu Démarrer et recherchez « Variables d'environnement ».
- Sélectionnez « Editer les variables d'environnement du système ».
- Dans la fenêtre Propriétés du système, cliquez sur le bouton Variables d'environnement.
- Dans la fenêtre Variables d'environnement, sous Variables système, recherchez la variable
Pathet sélectionnez-la. Cliquez sur Editer. - Dans la boîte de dialogue Edit Environment Variable, cliquez sur New et ajoutez le chemin vers le répertoire
binde Maven (C:\Napache-maven-3.9.7\Nbin). - Cliquez sur OK pour fermer toutes les boîtes de dialogue.
- Ajoutez
- Verify Maven Installation:
- Ouvrez une nouvelle invite de commande et exécutez-la :
mvn -v
- Cela devrait afficher la version de Maven et d'autres détails de l'environnement, confirmant que Maven est installé correctement.
- Ouvrez une nouvelle invite de commande et exécutez-la :
-
Navigate to Your Project Directory:
- Ouvrez une invite de commande et allez dans le répertoire contenant votre fichier
pom.xml:cd path\to\your\project
- Ouvrez une invite de commande et allez dans le répertoire contenant votre fichier
-
Run Maven Build and Tests:
- Exécutez la commande suivante pour nettoyer, construire et tester votre application :
mvn clean verify
- Si votre
pom.xmln'est pas dans le répertoire courant, vous pouvez spécifier le chemin vers celui-ci :mvn clean verify --file /path/to/pom.xml
- Exécutez la commande suivante pour nettoyer, construire et tester votre application :
-
mvn clean:- Cette commande supprime tous les fichiers générés par la compilation précédente. Cela inclut les classes compilées, les fichiers JAR et d'autres artefacts de compilation. Le nettoyage permet de s'assurer que tous les vestiges des constructions précédentes sont supprimés, ce qui permet d'éviter tout comportement inattendu dû à des artefacts périmés.
-
mvn verify:- Cette commande exécute une compilation complète du projet. Elle compile le code source, traite les ressources, compile le code compilé dans des JAR ou d'autres artefacts et exécute les tests.
- Unit Tests: Il s'agit de petits tests isolés qui vérifient la fonctionnalité d'unités de code individuelles (par exemple, des méthodes ou des classes). Ils sont généralement rapides et couvrent les cas limites.
- Integration Tests (Component Tests): Ces tests vérifient les interactions entre les différentes parties de l'application. Ils garantissent que les composants fonctionnent ensemble comme prévu et ont souvent une portée plus large, comme les interactions avec la base de données ou les appels de services externes.
Testcontainers sont des bibliothèques Java qui permettent aux développeurs d'exécuter des conteneurs Docker dans leurs tests. Elles fournissent des instances légères et jetables de bases de données, de courtiers de messages et d'autres services, ce qui rend les tests d'intégration plus fiables et plus faciles à mettre en place. Par exemple, dans notre projet, nous utilisons le PostgreSQL Testcontainer pour exécuter une instance PostgreSQL pendant les tests.
Tout d'abord, créez un répertoire .github/workflows dans votre référentiel de projet. Ce répertoire contiendra les fichiers de configuration des Actions GitHub.
mkdir -p .github/workflows
Créez un fichier nommé main.yml dans le répertoire .github/workflows avec le contenu suivant :
name: CI devops 2024
on:
# To begin you want to launch this job in main and develop
push:
branches:
- main
- develop
pull_request:
jobs:
test-backend:
runs-on: ubuntu-22.04
steps:
# Checkout your GitHub code using actions/checkout@v2.5.0
- uses: actions/checkout@v2.5.0
# Setup JDK 17 using actions/setup-java@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
# Build and test with Maven
- name: Build and test with Maven
run: mvn clean install
working-directory: ./backend api/simple-api-student-main-
Placez le fichier
main.ymldans votre dépôt GitHub :git add .github/workflows/main.yml git commit -m "Add GitHub Actions CI workflow" git push origin main -
Allez dans l'onglet « Actions » de votre dépôt GitHub. Vous devriez voir votre flux de travail s'exécuter. Si tout est configuré correctement, le flux de travail se terminera avec succès, indiqué par une coche verte.
-
Go to Your GitHub Repository Settings:
- Navigate to your GitHub repository and click on the "Settings" tab.
-
Access Secrets and Variables:
- In the left-hand menu, click on "Secrets and variables".
-
Add a New Repository Secret:
- Click on the "New repository secret" button.
-
Enter Your Docker Hub Username:
- In the "Name" field, enter
DOCKERHUB_USERNAME. - In the "Value" field, enter your Docker Hub username.
- Click on the "Add secret" button to save the secret.
- In the "Name" field, enter
-
Enter Your Docker Hub Password:
- Click on the "New repository secret" button again.
- In the "Name" field, enter
DOCKERHUB_PASSWORD. - In the "Value" field, enter your Docker Hub password.
- Click on the "Add secret" button to save the secret.
-
Go to Your GitHub Repository Settings:
- Navigate to your GitHub repository and click on the "Settings" tab.
-
Access Secrets and Variables:
- In the left-hand menu, click on "Secrets and variables".
-
Add a New Repository Secret:
- Click on the "New repository secret" button.
-
Enter Your Docker Hub Username:
- In the "Name" field, enter
DOCKERHUB_USERNAME. - In the "Value" field, enter your Docker Hub username.
- Click on the "Add secret" button to save the secret.
- In the "Name" field, enter
-
Enter Your Docker Hub Password:
- Click on the "New repository secret" button again.
- In the "Name" field, enter
DOCKERHUB_PASSWORD. - In the "Value" field, enter your Docker Hub password.
- Click on the "Add secret" button to save the secret.
Enhance your main.yml file to include steps for logging in to Docker Hub, building Docker images, and pushing them to Docker Hub. Here’s how you can do it:
name: CI/CD devops 2024
on:
push:
branches:
- main
- develop
pull_request:
jobs:
test-backend:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2.5.0
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
- name: Build and test with Maven
run: mvn clean install
working-directory: ./backend api/simple-api-student-main
build-and-push-docker-image:
needs: test-backend
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2.5.0
- name: Log in to Docker Hub
run: echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login -u "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin
- name: Build and push backend image
uses: docker/build-push-action@v3
with:
context: ./backend api/simple-api-student-main
tags: ${{ secrets.DOCKERHUB_USERNAME }}/tp-devops-simple-api:latest
push: ${{ github.ref == 'refs/heads/main' }}
- name: Build and push database image
uses: docker/build-push-action@v3
with:
context: ./postgres
tags: ${{ secrets.DOCKERHUB_USERNAME }}/tp-devops-database:latest
push: ${{ github.ref == 'refs/heads/main' }}
- name: Build and push httpd image
uses: docker/build-push-action@v3
with:
context: ./http
tags: ${{ secrets.DOCKERHUB_USERNAME }}/tp-devops-httpd:latest
push: ${{ github.ref == 'refs/heads/main' }}-
Triggers (
on):push: The workflow triggers on pushes tomainanddevelopbranches.pull_request: The workflow triggers on pull request events.
-
Jobs:
-
test-backend:
- runs-on: Specifies the runner, in this case,
ubuntu-22.04. - steps:
- actions/checkout@v2.5.0: Checks out the code from the repository.
- actions/setup-java@v3: Sets up JDK 17.
- Build and test with Maven: Runs
mvn clean installto build and test the backend.
- runs-on: Specifies the runner, in this case,
-
build-and-push-docker-image:
- needs: Specifies that this job depends on the successful completion of
test-backend. - runs-on: Specifies the runner, in this case,
ubuntu-22.04. - steps:
- actions/checkout@v2.5.0: Checks out the code from the repository.
- Log in to Docker Hub: Logs in to Docker Hub using the secrets
DOCKERHUB_USERNAMEandDOCKERHUB_PASSWORD. - Build and push backend image: Builds and pushes the backend Docker image to Docker Hub.
- Build and push database image: Builds and pushes the database Docker image to Docker Hub.
- Build and push httpd image: Builds and pushes the httpd Docker image to Docker Hub.
- needs: Specifies that this job depends on the successful completion of
-
In this step, you will learn how to configure your GitHub Actions pipeline to build and publish Docker images to Docker Hub on every commit to the main branch, as well as set up SonarCloud for quality gate analysis.
To publish Docker images, you need to ensure you log in to Docker Hub and push the images only on commits to the main branch. Here’s the updated main.yml configuration:
name: CI/CD devops 2024
on:
push:
branches:
- main
- develop
pull_request:
jobs:
test-backend:
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v2.5.0
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
- name: Build and test with Maven
run: mvn -B verify sonar:sonar -Dsonar.projectKey=justine-smmt -Dsonar.organization=sammut-justine -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=${{ secrets.SONAR_TOKEN }} --file pom.xml
working-directory: ./backend api/simple-api-student-main
build-and-push-docker-image:
needs: test-backend
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@v2.5.0
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build image and push backend
uses: docker/build-push-action@v3
with:
context: ./backend api/simple-api-student-main
tags: ${{ secrets.DOCKERHUB_USERNAME }}/tp-devops-simple-api-backend:latest
push: ${{ github.ref == 'refs/heads/main' }}
- name: Build image and push database
uses: docker/build-push-action@v3
with:
context: ./postgres
tags: ${{ secrets.DOCKERHUB_USERNAME }}/tp-devops-simple-api-database:latest
push: ${{ github.ref == 'refs/heads/main' }}
- name: Build image and push httpd
uses: docker/build-push-action@v3
with:
context: ./http
tags: ${{ secrets.DOCKERHUB_USERNAME }}/tp-devops-simple-api-httpd:latest
push: ${{ github.ref == 'refs/heads/main' }}-
Docker Login:
- The
Log in to Docker Hubstep usesdocker/login-action@v2to log in to Docker Hub using the credentials stored in GitHub Secrets.
- The
-
Build and Push Docker Images:
- Each
docker/build-push-action@v3step builds and pushes a Docker image. - The
contextspecifies the location of the Dockerfile. - The
tagsspecify the Docker image tag, and thepushparameter ensures the image is pushed only when the commit is on themainbranch.
- Each
-
Push the Configuration:
git add .github/workflows/main.yml git commit -m "Add Docker build and push steps to GitHub Actions" git push origin main -
Check GitHub Actions:
- Navigate to the "Actions" tab in your GitHub repository to verify the workflow execution.
- Ensure the workflow builds and pushes Docker images to Docker Hub on commits to the
mainbranch.
-
Create a SonarCloud Account:
- Go to SonarCloud and create a free-tier account.
- Create an organization and a project. Note down the
project keyandorganization key.
-
Add SonarCloud Token to GitHub Secrets:
- In your GitHub repository settings, add a new secret named
SONAR_TOKENand paste your SonarCloud token.
- In your GitHub repository settings, add a new secret named
Modify the Maven build step to include SonarCloud analysis:
- name: Build and test with Maven
run: mvn -B verify sonar:sonar -Dsonar.projectKey=devops-cjassey_project-devops -Dsonar.organization=devops-cjassey -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=${{ secrets.SONAR_TOKEN }} --file pom.xml
working-directory: ./backend api/simple-api-student-main
- The
Build and test with Mavenstep now includes parameters for SonarCloud analysis.-Dsonar.projectKey: Your SonarCloud project key.-Dsonar.organization: Your SonarCloud organization key.-Dsonar.host.url: The SonarCloud URL.-Dsonar.login: Your SonarCloud token stored in GitHub Secrets.
-
Push the Configuration:
git add .github/workflows/main.yml git commit -m "Add SonarCloud analysis to GitHub Actions" git push origin main -
Check GitHub Actions:
- Navigate to the "Actions" tab in your GitHub repository to verify the workflow execution.
- Ensure the workflow performs SonarCloud analysis during the build process.
-
Check SonarCloud:
- Go to your SonarCloud dashboard to view the analysis report for your project.
By following these steps, you have configured a CI/CD pipeline that:
- Builds and pushes Docker images to Docker Hub on commits to the
mainbranch. - Integrates SonarCloud for code quality analysis, ensuring a maintainable and secure codebase.
This guide will walk you through setting up a project-specific inventory for Ansible and executing some basic commands to interact with your remote server. You will learn how to create the necessary directories and files, configure your inventory, and use Ansible modules to gather information and manage your server.
- Windows Linux Subsystem (WSL): Ensure that WSL is installed and configured on your Windows machine.
- Ansible: We will install Ansible in WSL.
- SSH Private Key: You will need your private key to connect to your remote server.
Start by creating the required directories and files for your Ansible project:
mkdir -p /mnt/c/Users/Dell/OneDrive\ -\ Fondation\ EPF/documents/4a\ semestre\ 2\ EPF/Devops/my-project/ansible/inventoriesNavigate to your project directory:
cd /mnt/c/Users/Dell/OneDrive\ -\ Fondation\ EPF/documents/4a\ semestre\ 2\ EPF/Devops/my-projectCreate the ansible directory:
mkdir ansible
cd ansibleCreate the inventories directory:
mkdir inventories
cd inventoriesCreate the setup.yml file:
touch setup.ymlEdit the setup.yml file and add the following configuration:
all:
vars:
ansible_user: centos
ansible_ssh_private_key_file: ~/.ssh/id_rsa
children:
prod:
hosts: justine.sammut.takima.cloudUse the ping module to test the connectivity with your server:
ansible all -i inventories/setup.yml -m pingExpected output:
justine.sammut.takima.cloud | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}Use the setup module to gather information about your host:
ansible all -i inventories/setup.yml -m setup -a "filter=ansible_distribution*"Expected output:
justine.sammut.takima.cloud | SUCCESS => {
"ansible_facts": {
"ansible_distribution": "CentOS",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/redhat-release",
"ansible_distribution_file_variety": "RedHat",
"ansible_distribution_major_version": "7",
"ansible_distribution_release": "Core",
"ansible_distribution_version": "7.9",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}Start by creating a simple playbook to test the connection to your server.
Create the playbook.yml file:
cd /mnt/c/Users/Dell/OneDrive\ -\ Fondation\ EPF/documents/4a\ semestre\ 2\ EPF/Devops/my-project/ansible
touch playbook.ymlEdit the playbook.yml file and add the following content:
- hosts: all
gather_facts: false
become: true
tasks:
- name: Test connection
ping:Execute the playbook:
ansible-playbook -i inventories/setup.yml playbook.ymlExpected output:
PLAY [all] **************************************************************************************************************************
TASK [Test connection] **************************************************************************************************************
ok: [justine.sammut.takima.cloud]
PLAY RECAP **************************************************************************************************************************
justine.sammut.takima.cloud : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Edit the playbook.yml file to install Docker on your server:
nano playbook.ymlReplace the existing content with:
- hosts: all
gather_facts: false
become: true
tasks:
- name: Install device-mapper-persistent-data
yum:
name: device-mapper-persistent-data
state: latest
- name: Install lvm2
yum:
name: lvm2
state: latest
- name: Add Docker repository
command:
cmd: sudo yum-config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
- name: Install Docker
yum:
name: docker-ce
state: present
- name: Install python3
yum:
name: python3
state: present
- name: Install Docker with Python 3
pip:
name: docker
executable: pip3
vars:
ansible_python_interpreter: /usr/bin/python3
- name: Make sure Docker is running
service:
name: docker
state: started
tags: dockerExecute the playbook:
ansible-playbook -i inventories/setup.yml playbook.ymlExpected output:
PLAY [all] **************************************************************************************************************************
TASK [Install device-mapper-persistent-data] ****************************************************************************************
changed: [clement.jassey.takima.cloud]
TASK [Install lvm2] *****************************************************************************************************************
changed: [clement.jassey.takima.cloud]
TASK [Add Docker repository] ********************************************************************************************************
changed: [clement.jassey.takima.cloud]
TASK [Install Docker] ***************************************************************************************************************
changed: [clement.jassey.takima.cloud]
TASK [Install python3] **************************************************************************************************************
changed: [clement.jassey.takima.cloud]
TASK [Install Docker with Python 3] *************************************************************************************************
changed: [clement.jassey.takima.cloud]
TASK [Make sure Docker is running] **************************************************************************************************
changed: [clement.jassey.takima.cloud]
PLAY RECAP **************************************************************************************************************************
clement.jassey.takima.cloud : ok=7 changed=7 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Create a Docker role for cleaner task management:
ansible-galaxy init roles/dockerMove the Docker installation tasks to the role:
Edit the tasks/main.yml file in the roles/docker directory and add the following content:
---
# tasks file for roles/docker
- name: Install device-mapper-persistent-data
yum:
name: device-mapper-persistent-data
state: latest
- name: Install lvm2
yum:
name: lvm2
state: latest
- name: Add Docker repository
command:
cmd: sudo yum-config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
- name: Install Docker
yum:
name: docker-ce
state: present
- name: Install python3
yum:
name: python3
state: present
- name: Install Docker with Python 3
pip:
name: docker
executable: pip3
vars:
ansible_python_interpreter: /usr/bin/python3
- name: Make sure Docker is running
service:
name: docker
state: started
tags: dockerEdit the handlers/main.yml file in the roles/docker directory and add the following content:
---
# handlers file for roles/docker
- name: Restart Docker
systemd:
name: docker
state: restarted
enabled: yesEdit the playbook.yml file to use the Docker role:
- hosts: all
gather_facts: false
become: true
roles:
- role: dockerExecute the playbook to apply the role:
ansible-playbook -i inventories/setup.yml playbook.ymlYou have now successfully created and executed both simple and advanced Ansible playbooks, tested server connectivity, installed Docker, and refactored your tasks into roles for better organization. This setup will help you efficiently manage and provision your servers using Ansible.
This guide walks through the steps to deploy a dockerized application using Ansible. We will create specific roles to handle different parts of the deployment process, including installing Docker, creating a network, launching the database, the application, and the proxy. Each part will use the docker_container module to start the respective Docker containers.
- Install Docker: Install Docker on the managed server.
- Create Network: Create a Docker network for the containers to communicate.
- Launch Database: Pull and run the database container.
- Launch App: Pull and run the application container.
- Launch Proxy: Pull and run the proxy container.
- Create the roles using
ansible-galaxy:
ansible-galaxy init roles/network
ansible-galaxy init roles/database
ansible-galaxy init roles/launch_app
ansible-galaxy init roles/launch_proxyThe main playbook, playbook.yml, which includes all the roles:
- hosts: all
gather_facts: false
become: true
roles:
- docker
- network
- database
- launch_app
- launch_proxyTasks file (roles/docker/tasks/main.yml):
---
# tasks file for roles/docker
- name: Install device-mapper-persistent-data
yum:
name: device-mapper-persistent-data
state: latest
- name: Install lvm2
yum:
name: lvm2
state: latest
- name: add repo docker
command:
cmd: sudo yum-config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
- name: Install Docker
yum:
name: docker-ce
state: present
- name: Install python3
yum:
name: python3
state: present
- name: Install docker with Python 3
pip:
name: docker
executable: pip3
vars:
ansible_python_interpreter: /usr/bin/python3
- name: Make sure Docker is running
service:
name: docker
state: started
tags: docker
- name: Log in to Docker Hub
docker_login:
username: cjassey
password: password_dockerhub
reauthorize: yesTasks file (roles/network/tasks/main.yml):
---
# tasks file for roles/network
- name: Create a network
community.docker.docker_network:
name: app-networkTasks file (roles/database/tasks/main.yml):
---
# tasks file for roles/database
- name: Pull the BDD image
docker_image:
name: cjassey/tp-devops-simple-api-database
tag: latest
source: pull
- name: Run BDD
docker_container:
state: started
name: mypostgres
image: cjassey/tp-devops-simple-api-database
networks:
- name: "app-network"Tasks file (roles/launch_app/tasks/main.yml):
---
# tasks file for roles/launch_app
- name: Pull the API Image
docker_image:
name: cjassey/tp-devops-simple-api-backend
tag: latest
source: pull
- name: Run API
docker_container:
name: simple-api-container-student2
image: cjassey/tp-devops-simple-api-backend:latest
networks:
- name: "app-network"
state: startedTasks file (roles/launch_proxy/tasks/main.yml):
---
# tasks file for roles/launch_proxy
- name: Pull the proxy container
docker_image:
name: cjassey/tp-devops-simple-api-httpd
tag: latest
source: pull
- name: Run the proxy container
docker_container:
name: httpd-1
image: cjassey/tp-devops-simple-api-httpd
ports:
- "80:80"
networks:
- name: "app-network"Run the playbook to deploy the application:
ansible-playbook -i inventories/setup.yml playbook.ymlOnce the playbook runs successfully, verify the deployment by accessing the API endpoints:
-
Check the base endpoint:
http://clement.jassey.takima.cloud
Expected response:
{ "id": 4, "content": "Hello, World!" } -
Check the departments endpoint:
http://clement.jassey.takima.cloud/departments/IRC/students
Expected response:
[ { "id": 1, "firstname": "Eli", "lastname": "Copter", "department": { "id": 1, "name": "IRC" } } ]
You have now successfully set up and deployed your dockerized application using Ansible. This guide covers the creation of roles, configuring tasks for Docker, and running the playbook to deploy the application on a managed server. This structured approach ensures a clean and maintainable deployment process.