Per spiegare nel dettaglio questa procedura partiamo da un progetto Spring Boot già pronto del tutorial precedente. Per iniziare cloniamo il progetto tramite il comando git:
git clone -b integrazione-swagger2-springboot-rest https://git.saverioriotto.it/saverioriotto.it/spring-boot-rest-tutorial.git
Per iniziare la dockerizzazione dell'applicazione, creremo un Dockerfile con il seguente contenuto:
FROM maven:3.8.2-jdk-8
LABEL maintainer="Saverio Riotto [email protected]"
WORKDIR /spring-app-rest
COPY . .
RUN mvn clean install
CMD mvn spring-boot:run
Questo file contiene le seguenti informazioni:
FROM: immagine di base, utilizzeremo maven con jdk-8
LABEL: chi gestisce l'immagine.
COPY : Docker copia tutti i file del progetto nell'immagine.
RUN: comando maven da eseguire per compilare il progetto e portare giù le dipendenze necessarie
CMD: comando maven per avviare il progetto Spring Boot
Per creare un'immagine dal nostro Dockerfile, dobbiamo eseguire il comando 'docker build':
docker build --tag=spring-boot-rest-app:latest .
Infine, siamo in grado di eseguire il container dalla nostra immagine:
docker run -p8080:8080 spring-boot-rest-app:latest
Dopo aver lanciato quest'ultimo comando la nostra applicazione sara raggiungibile tramite chiamata HTTP sulla porta 8080. (es: http://localhost:8080/api/).
In questo modo abbiamo avviato un singolo container con la nostra applicazione e senza parametri di configurazione.
I comandi Docker e i Dockerfile sono particolarmente adatti per la creazione di singoli container. Tuttavia, se vogliamo operare su una rete di applicazioni isolate, la gestione dei container diventa rapidamente complessa e disordinata.
Per risolvere questo problema, ricorriamo al Docker Compose. Questo strumento viene fornito con il proprio file di compilazione in formato YAML ed è più adatto per la gestione di più contenitori. Ad esempio, è in grado di avviare o arrestare un insieme di servizi in un comando o unire l'output dei logs di più servizi in un unico pseudo-tty e tanto altro ancora che puoi scoprire tramite un precedente articolo chiamato: Docker Compose: Che cos'è e come si usa.
Prendiamo sempre il nostro progetto e cerchiamo di dividerlo in più servizi creando il nostro docker-compose.yml :
version: '3.9'
services:
rest-server:
container_name: rest-server
build:
dockerfile: Dockerfile
ports:
- $SPRING_DOCKER_PORT:$SPRING_DOCKER_PORT
networks:
- spring-network
depends_on:
- mariadb
restart: on-failure
env_file: ./.env
environment:
SPRING_APPLICATION_JSON: '{
"spring.datasource.url" : "jdbc:mariadb://$DB_HOST:3306/$DB_NAME?useSSL=false",
"spring.datasource.username" : "$DB_USER",
"spring.datasource.password" : "$DB_PASSWORD",
"spring.jpa.properties.hibernate.dialect" : "org.hibernate.dialect.MariaDB10Dialect",
"spring.jpa.hibernate.ddl-auto" : "update",
"saverioriotto.app.jwtSecret" : "sRSecretKey",
"saverioriotto.app.jwtExpirationMs" : "86400000",
"server.port" : "$SPRING_DOCKER_PORT"}'
mariadb:
image: mariadb:10.2
container_name: mariadb
env_file: ./.env
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- mariadb:/var/lib/mysql
networks:
- spring-network
restart: on-failure
phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: phpma
links:
- mariadb:mariadb
ports:
- 80:80
environment:
PMA_HOST: mariadb
PMA_PORT: 3306
networks:
- spring-network
networks:
spring-network:
driver: bridge
volumes:
mariadb:
driver: local
version: specifica quale versione del formato deve essere utilizzata. Questo è un campo obbligatorio. Qui utilizziamo la versione 3.9, mentre il formato legacy è "1".
services: ogni oggetto in questa chiave definisce un servizio, alias container. Questa sezione è obbligatoria.
build: se fornito, docker-compose è in grado di creare un'immagine da un Dockerfile.
image: dice a Docker quale nome dovrebbe dare all'immagine quando vengono utilizzate le funzioni di build. In caso contrario, sta cercando questa immagine nella libreria o nel repository remoto.
networks: questo è l'identificatore delle reti da utilizzare. Specificato con un dato nome-valore. In questo esempio, lasciamo che docker-compose crei per noi una rete denominata di tipo 'bridge'.
depends_on: utilizzato per impostare l'ordine in cui i servizi devono essere avviati e arrestati.Nel nostro caso prima di avviare il servizio rest abbiamo bisogno che il container “mariadb” sia già stato avviato. Stessa situazione per il phpmyadmin
environment: In questa sezione dichiariamo tutte le variabili d’ambiente che vengono richiamate, nel nostro caso, da un file .env:
DB_USER=tutorial_user
DB_PASSWORD=tut04i@lu53r
DB_NAME=tutorialdb
DB_ROOT_PASSWORD=tut04i@lroo1
DB_HOST=mariadb
SPRING_DOCKER_PORT=8080
La variabile d'ambiente SPRING_APPLICATION_JSON invece contiene la configurazione parametrizzata del file application.properties di Spring Boot.
Prima di continuare, controlliamo che il nostro docker-compose.yml non abbiamo errori di sintassi con il seguente comando:
docker-compose config
Se risulta corretto possiamo avviare la build che costruirà tutti i container configurati con il seguente comando:
docker-compose up --build
Questo avvierà tutti e tre i container dichiarati come servizi in con un unico comando.
Per fermare i container, rimuoverli da Docker e rimuovere da esso le reti connesse Possiamo usare il comando opposto:
docker-compose down
In questo articolo abbiamo appreso come creare immagini Docker personalizzate, eseguire un'applicazione Spring Boot come container Docker e creare più container con un singolo docker-compose.yaml.
Il codice sorgente di questo tutorial lo trovi su Github.