From 19ecd5b015dffb788db52526343684dc226ca6d7 Mon Sep 17 00:00:00 2001 From: Marica Antonacci Date: Mon, 9 Sep 2024 17:22:43 +0200 Subject: [PATCH] Update 2024 (#9) * Add compose section * Add "#include " to hello.c example (#5) * Update intro and container sections (#6) * Fix automation section (#8) * Add Github action section * Update automation section * Add Docker compose section (#7) * Add Compose content * Add Compose content * Add Compose content * Add compose section * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content * Add Compose content --------- Co-authored-by: Gioacchino Vino --------- Co-authored-by: Lisa Co-authored-by: jvino Co-authored-by: Gioacchino Vino --- docs/compose/concepts.md | 710 +++++++++++++++++++++++++++++ docs/compose/hands-on.md | 121 +++++ docs/container/example.md | 261 +++++------ docs/container/health_checks.md | 2 +- docs/container/manipulation.md | 48 +- docs/image/automation/exercises.md | 8 - docs/image/automation/ghaction.md | 106 +++++ docs/image/automation/index.md | 105 +---- docs/image/dockerfile/copy.md | 2 + docs/intro/hello-world.md | 4 +- docs/intro/images.md | 48 +- docs/intro/info.md | 24 +- docs/intro/install.md | 4 +- mkdocs.yml | 7 +- 14 files changed, 1127 insertions(+), 323 deletions(-) create mode 100644 docs/compose/concepts.md create mode 100644 docs/compose/hands-on.md delete mode 100644 docs/image/automation/exercises.md create mode 100644 docs/image/automation/ghaction.md diff --git a/docs/compose/concepts.md b/docs/compose/concepts.md new file mode 100644 index 0000000..b3a6a41 --- /dev/null +++ b/docs/compose/concepts.md @@ -0,0 +1,710 @@ + +**Docker Compose** is a utility designed to define and execute multi-container Docker applications. It facilitates the management of interconnected containers as a unified entity + +### Docker compose file + +Docker uses a simple YAML file to describe multi-container application. + +This file is called a "docker-compose file" + +Following a simple example of a docker compose file: + +```yaml +services: + db: + image: influxdb:2.7 + volumes: + - db_data:/var/lib/influxdb2:rw + ports: + - "8086:8086" + networks: + - db_net + +volumes: + db_data: + +networks: + db_net: +``` + +In the YAML file you can notice an basic structure: + +* the **services** keyword let you list all services of the application. +* **db** is the arbitraty name of the service, it can be anything you like as long as it's unique. +* inside each service, with the **image**, **volumes**, **ports** and **networks** keywords you can configure the execution of the service +* the **volumes** keyword allows to define volumes to be attach in the containers. +* the **networks** keyword allows to define networks to be used in the containers. + +### Docker compose CLI + +The Docker CLI lets you interact with your Docker Compose applications through the `docker compose` command, and its subcommands. + +Using the CLI, you can manage the lifecycle of your multi-container applications defined in the compose.yaml file. + +The CLI commands enable you to start, stop, and configure your applications effortlessly. + +* **docker compose up**: initializes and starts the application environment +* **docker compose start**: starts the application environment +* **docker compose restart**: restarts the already created application environment +* **docker compose stop**: stops the application environment +* **docker compose down**: stops and destroys the application environment + +#### Most used docker compose commands +* `docker compose up`: initializes, starts the application environment and shows logs without return to command line +* `docker compose up -d`: initializes and starts the application environment in detacted mode +* `docker compose ps`: lists the running containers/services +* `docker compose down -v`: stops and destroys the application environment and volumes +* `docker compose logs`: shows application logs + +#### Start your first multi-container application + +Let's start a multi-container application. At this point it's not important the content of the docker compose file. + +Docker compose file: + +```yaml +services: + db: + image: influxdb:2.7 + volumes: + - db_data:/var/lib/influxdb2:rw + ports: + - "8086:8086" + networks: + - db_net + +volumes: + db_data: + +networks: + db_net: +``` + +Commands: + +```bash +user@vm:~/prova_1$ docker compose up -d +✔ db 10 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿] 0B/0B Pulled 39.4s +[+] Running 3/3 +✔ Network prova_1_db_net Created +✔ Volume "prova_1_db_data" Created +✔ Container prova_1-db-1 Started + +user@vm:~/prova_1$ docker container ps +CONTAINERID IMAGE NAMES +Be72e5.. influxdb:2.7 prova_1_db_1 + +user@vm:~/prova_1$ docker volume ls +DRIVER VOLUME NAME +local 46f4a.. +local prova_1_db_data + +user@vm:~/prova_1$ docker network ls +NETWORK ID NAME DRIVER SCOPE +51039c996454 bridge bridge local +85ffa41af96f host host local +d6f329122060 none null local +ec31eefd60d5 prova_1_db_net bridge local +``` + +!!! tip + Every object name (image, volume and network) starts with `prova_1` that represents the folder name containing the docker compose file. + +#### Stop your first multi-container application + +Commands: + +```bash +user@vm:~/prova_1$ docker compose down +[+] Running 2/2 + ✔ Container prova_1-db-1 Removed + ✔ Network prova_1_db_net Removed + +user@vm:~/prova_1$ docker container ps +CONTAINERID IMAGE STATUS NAMES + +user@vm:~/prova_1$ docker volume ls +DRIVER VOLUME NAME +local 46f4.. +local prova_1_db_data + +user@vm:~/prova_1$ docker network ls +NETWORK ID NAME DRIVER SCOPE +51039c996454 bridge bridge local +85ffa41af96f host host local +d6f329122060 none null local +``` + +Some comments: +- Volumes are not removed with `docker compose down` +- Compose preserves all volumes used by your services +- Data inside volume is not lost and can be reused once the application is restarted +- To remove volume as well, use `docker compose down --volumes` or `docker compose down -v` + +### Project name + +Compose uses project names to isolate multi-container applications from each others. + +If not set, the folder name is taken as project name. + +!!! tip + A custom project name can be set using the `-p` command line option or the `COMPOSE_PROJECT_NAME` environment variable. + +```bash +user@vm:~$ cd .. +user@vm:~$ cp -r prova_1/ prova_2/ +user@vm:~$ cd prova_2 + +user@vm:~/prova_2$ docker compose up -d +[+] Running 3/3 +✔ Network prova_2_db_net Created +✔ Volume "prova_2_db_data" Created +✔ Container prova_2-db-1 Started + +user@vm:~/prova_2$ docker ps +CONTAINERID IMAGE NAMES +297f44.. influxdb:2.7 prova_2_db_1 + +user@vm:~/prova_2$ docker compose down +[+] Running 2/2 +✔ Container prova_2-db-1 Removed +✔ Network prova_2_db_net Removed +``` + +### Custom Network configuration + +By default Compose sets up a single network for your application. + +Each container joins the default network and is both **reachable** by other containers on that network and **discoverable** by them at a hostname identical to the container name. + +If you make a configuration change to a service and run `docker compose up` to update it, the old container is removed and the new one joins the network under a different IP address but the same name. So it is suggested to use hostnames instead of IPs to connect services. + +You can specify your custom network with the top-level networks key. Following an example. + +```yaml +networks: + front: + driver: bridge + driver_opts: + com.docker.network.enable_ipv6: "true" + ipam: + driver: default + config: + - subnet: 172.16.238.0/24 + gateway: 172.16.238.1 + - subnet: "2001:3984:3989::/64" + gateway: "2001:3984:3989::1" +``` + +### Write your first docker compose file + +Let's learn how to write a docker compose file by converting an application described from command line instructions to the corresponding YAML format file. + +```bash +docker volume create influxdb-storage +export INFLUXDB_USERNAME=corsodocker2024 +export INFLUXDB_PW=corsodocker2024 +docker container run --name influxdb \ + -p 8086:8086 \ + -v influxdb-storage:/var/lib/influxdb \ + -e DOCKER_INFLUXDB_INIT_MODE=setup \ + -e DOCKER_INFLUXDB_INIT_USERNAME=${INFLUXDB_USERNAME} \ + -e DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUXDB_PW} \ + -e DOCKER_INFLUXDB_INIT_ORG=INFN \ + -e DOCKER_INFLUXDB_INIT_BUCKET=INFN-BUCKET \ + influxdb:2.7 + +docker volume create grafana-storage +export GRAFANA_USERNAME=corsodocker2024 +export GRAFANA_PW=corsodocker2024 +docker container run --name grafana \ + -p 3000:3000 \ + -v grafana-storage:/var/lib/grafana \ + -e GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} \ + -e GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PW} \ + grafana/grafana:11.2.0-ubuntu +``` + +The resulting YAML file is: + +```yaml +services: + influxdb: + image: influxdb:2.7 + ports: + - '8086:8086' + networks: + - my_net + volumes: + - influxdb-storage:/var/lib/influxdb + environment: + - DOCKER_INFLUXDB_INIT_MODE=setup + - DOCKER_INFLUXDB_INIT_USERNAME=${INFLUXDB_USERNAME} + - DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUXDB_PW} + - DOCKER_INFLUXDB_INIT_ORG=INFN + - DOCKER_INFLUXDB_INIT_BUCKET=INFN-BUCKET + + grafana: + image: grafana/grafana:11.2.0-ubuntu + ports: + - '3000:3000' + networks: + - my_net + volumes: + - grafana-storage:/var/lib/grafana + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PW} + +volumes: + influxdb-storage: {} + grafana-storage: {} + +networks: + my_net: {} +``` + +As you can see, there is a one-to-one correspondence between information in the command line instructions and the docker compose file. + +#### Using default network definition + +Docker Compose creates a default network if not present any network definitions in the docker compose file. In such a case, the section `networks` inside each application should be avoided as well. In this second scenario, the YAML file become: + +```yaml +services: + influxdb: + image: influxdb:2.7 + ports: + - '8086:8086' + volumes: + - influxdb-storage:/var/lib/influxdb + environment: + - DOCKER_INFLUXDB_INIT_MODE=setup + - DOCKER_INFLUXDB_INIT_USERNAME=${INFLUXDB_USERNAME} + - DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUXDB_PW} + - DOCKER_INFLUXDB_INIT_ORG=INFN + - DOCKER_INFLUXDB_INIT_BUCKET=INFN-BUCKET + grafana: + image: grafana/grafana:11.2.0-ubuntu + ports: + - '3000:3000' + volumes: + - grafana-storage:/var/lib/grafana + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PW} + +volumes: + influxdb-storage: {} + grafana-storage: {} +``` +#### Environment variable definition + +As you can see from the docker compose file above, the environment variable values are inserted directly inside the YAML file. This could be unacceplable in some cases. + +A second approach allows to link existed environment variables by inserting their names inside the docker compose file. + +```yaml +services: + influxdb: + image: influxdb:2.7 + ports: + - '8086:8086' + volumes: + - influxdb-storage:/var/lib/influxdb + environment: + - DOCKER_INFLUXDB_INIT_MODE=setup + - DOCKER_INFLUXDB_INIT_USERNAME=${INFLUXDB_USERNAME} + - DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUXDB_PW} + - DOCKER_INFLUXDB_INIT_ORG=INFN + - DOCKER_INFLUXDB_INIT_BUCKET=INFN-BUCKET + + grafana: + image: grafana/grafana:11.2.0-ubuntu + ports: + - '3000:3000' + volumes: + - grafana-storage:/var/lib/grafana + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PW} + +volumes: + influxdb-storage: {} + grafana-storage: {} +``` + +The above multi-container application can be started with the following commands: + +```bash +export INFLUXDB_USERNAME=corsodocker2024 +export INFLUXDB_PW=corsodocker2024 +export GRAFANA_USERNAME=admin +export GRAFANA_PW=admin +docker compose up +``` + +Or write a further file containing all environment variables. This file must be named `.env`. + +```bash +user@vm:~/example$ cat .env +INFLUXDB_USERNAME=corsodocker2024 +INFLUXDB_PW=corsodocker2024 +GRAFANA_USERNAME=corsodocker2024 +GRAFANA_PW=corsodocker2024 +``` + +Docker checks if in the directory is present a `.env` file. In a such a case, it will import the environment variables when the multi-container application is started. + +A third approach involves defining an environment variable file per service and inserting its name within the service definition, as show below. + +Environment variable files' content: + +```bash +user@vm:~/example$ cat influxdb.env +DOCKER_INFLUXDB_INIT_MODE=setup +DOCKER_INFLUXDB_INIT_USERNAME=corsodocker2024 +DOCKER_INFLUXDB_INIT_PASSWORD=corsodocker2024 +DOCKER_INFLUXDB_INIT_ORG=INFN +DOCKER_INFLUXDB_INIT_BUCKET=INFN-BUCKET + +user@vm:~/example$ cat grafana.env +GF_SECURITY_ADMIN_USER=corsodocker2024 +GF_SECURITY_ADMIN_PASSWORD=corsodocker2024 +``` + +Docker compose file: + +```yaml +services: + influxdb: + image: influxdb:2.7 + ports: + - '8086:8086' + volumes: + - influxdb-storage:/var/lib/influxdb + env_file: + - influxdb.env + + grafana: + image: grafana/grafana:11.2.0-ubuntu + ports: + - '3000:3000' + volumes: + - grafana-storage:/var/lib/grafana + env_file: + - grafana.env + +volumes: + influxdb-storage: {} + grafana-storage: {} +``` + +##### Further comments + +Environment variables offer a flexible way to customize your application. For example, you can use them to specify the image version of a service: + +```yaml +service: + influxdb: + image: influxdb:{$INFLUX_VERSION} +``` + +Default values are allowed: + +```yaml +service: + influxdb: + image: influxdb:{$INFLUX_VERSION:-2.7} +``` + +The default value should be placed after the `:-` characters. + +Since more approaches are supported, Docker compose uses the following priority order, overwriting the less important with the higher ones: + +When multiple approches are used, Docker compose prioritizes configuration as follows, with high-priorit values overriding lower-priority ones: +1. Compose file (highest important) +2. Shell environment variables +3. Environment file +4. Dockerfile +5. Undefined variables (lowest important) + +#### Health checks +Similar to the command-line interface, you can specify health checks for services within a Docker Compose file, as demonstrated below. + +```bash +docker volume create influxdb-storage +export INFLUXDB_USERNAME=admin +export INFLUXDB_PW=admin +docker container run --name influxdb + -p 8086:8086 \ + -v influxdb-storage:/var/lib/influxdb \ + -e DOCKER_INFLUXDB_INIT_MODE=setup \ + -e DOCKER_INFLUXDB_INIT_USERNAME=${INFLUXDB_USERNAME} \ + -e DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUXDB_PW} \ + -e DOCKER_INFLUXDB_INIT_ORG=INFN \ + -e DOCKER_INFLUXDB_INIT_BUCKET=INFN-BUCKET \ + --health-cmd='curl -f http://localhost:8086||exit 1' \ + --health-start-period=30s \ + --health-interval= 30s \ + --health-timeout=10s \ + --health-retries=4 \ + influxdb:2.7 +``` + +Docker compose file: + +```yaml +services: + influxdb: + image: influxdb:2.7 + ports: + - '8086:8086' + volumes: + - influxdb-storage:/var/lib/influxdb + environment: + - DOCKER_INFLUXDB_INIT_MODE=setup + - DOCKER_INFLUXDB_INIT_USERNAME=${INFLUXDB_USERNAME} + - DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUXDB_PW} + - DOCKER_INFLUXDB_INIT_ORG=INFN + - DOCKER_INFLUXDB_INIT_BUCKET=INFN-BUCKET + healthcheck: + test: "curl --fail http://localhost:8086 || exit 1" + start_period: 30s + interval: 30s + timeout: 10s + retries: 4 +``` + +### Dependencies + +Applications often have dependencies between services, requiring some to start before others. + +Docker Compose uses the `depends_on` keyword to define these dependencies. + +For instance, we can configure Grafana to start only after InfluxDB is running. + +The Docker Compose file becomes: + +```yaml +services: + influxdb: + image: influxdb:2.7 + ports: + - '8086:8086' + volumes: + - influxdb-storage:/var/lib/influxdb + environment: + - DOCKER_INFLUXDB_INIT_MODE=setup + - DOCKER_INFLUXDB_INIT_USERNAME=${INFLUXDB_USERNAME} + - DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUXDB_PW} + - DOCKER_INFLUXDB_INIT_ORG=INFN + - DOCKER_INFLUXDB_INIT_BUCKET=INFN-BUCKET + + grafana: + image: grafana/grafana:11.2.0-ubuntu + ports: + - '3000:3000' + volumes: + - grafana-storage:/var/lib/grafana + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} + depends_on: + - influxdb + +volumes: + influxdb-storage: + grafana-storage: +``` + +#### Waiting for a service is ready + +Certain applications require tools to be fully functional, not just running. Health checks can determine when a tool is ready for use. + +The Docker compose file becomes: + +```yaml +services: + influxdb: + image: influxdb:2.7 + ports: + - '8086:8086' + volumes: + - influxdb-storage:/var/lib/influxdb + environment: + - DOCKER_INFLUXDB_INIT_MODE=setup + - DOCKER_INFLUXDB_INIT_USERNAME=${INFLUXDB_USERNAME} + - DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUXDB_PW} + - DOCKER_INFLUXDB_INIT_ORG=INFN + - DOCKER_INFLUXDB_INIT_BUCKET=INFN-BUCKET + healthcheck: + test: "curl --fail http://localhost:8086 || exit 1" + start_period: 30s + interval: 30s + timeout: 10s + retries: 4 + + grafana: + image: grafana/grafana:11.2.0-ubuntu + ... + depends_on: + influxdb: + condition: service_healthy +``` + +### Profiles + +Profiles in Docker Compose offer a way to tailor your application for different scenarios by selectively activating or deactivating services. + +You can assign services to zero or more profiles. + +Unassigned services always start, while assigned ones start only when their corresponding profile is active. + +Let's considering the following Docker compose file + +```yaml +services: + frontend: + image: frontend + profiles: + - frontend + + phpmyadmin: + image: phpmyadmin + depends_on: + - db + profiles: + - debug + + backend: + image: backend + + db: + image: mysql +``` + +!!! tip + - the `db` service is always started since it does not contain the `profile` keyword + - the `phpmyadmin` service is started only when the `debug` profile is enabled + - the `frontend` service is started only when the `frontend` profile is enabled + +Examples: + +```bash +docker compose up # Only the db service is started +docker compose --profile frontend up # Only the db and frontend services are started +COMPOSE_PROFILES=frontend docker compose up # Other syntax for the above command + +docker compose --profile frontend --profile debug up # All services are started +COMPOSE_PROFILES=frontend,debug docker compose up # Other syntax for the above command +``` + +### Build Dockerfile and run a multi-container application + + +Within the image section of each service, Docker Compose defines the image used. + +You can specify a custom image built at runtime using a Dockerfile. + +Replace the `image` keyword with `build` for such services. + +Here's an example of a single-service application using a custom `python:3` image. + +Folder content: + +```bash +user@vm:~/prova_4$ ls -l +Dockerfile +requirements +docker-compose.yml +my-script.py +``` + +Dockerfile file content: + +```dockerfile +FROM python:3 + +COPY requirements /requirements +RUN pip install -r requirements +COPY my-script.py /my-script.py + +CMD [ "python3", "/my-script.py"] +``` + +Requirements file content: + +```bash +pandas +numpy +``` + +my-script file content: + +```python +import socket +import sys +from time import sleep +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +server_address = ('localhost', 1234) +print(f'starting up on {server_address[0]} port {server_address[1]}') +sock.bind(server_address) +sleep(60) +``` + +Docker compose file content: + +```yaml +services: + my_service: + build: . + ports: + - '1234:1234' + volumes: + - dir_data:/data +``` + +#### Let's start the application: + +!!! tip + - using the `--build` option forces Docker to rebuild the image + + +=== "Command" + ```bash + docker compose up -d --build + ``` +=== "Output" + ```bash + Creating network "prova_4_default" with the default driver + Building my_service + Sending build context to Docker daemon 5.12kB + Step 1/4 : FROM python:3 + ---> de529ffbdb66 + Step 2/4 : COPY requirements ./ + ---> 8f6840fe4dab + Step 3/4 : RUN pip install --no-cache-dir -r requirements.txt + ---> Running in 363ffa40779c + Collecting pandas + Downloading pandas-1.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (11.7 MB) + Collecting numpy + Downloading numpy-1.22.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (16.8 MB) + Collecting python-dateutil>=2.8.1 + Downloading python_dateutil-2.8.2-py2.py3-none-any.whl (247 kB) + Collecting pytz>=2020.1 + Downloading pytz-2021.3-py2.py3-none-any.whl (503 kB) + Collecting six>=1.5 + Downloading six-1.16.0-py2.py3-none-any.whl (11 kB) + Installing collected packages: six, pytz, python-dateutil, numpy, pandas + Successfully installed numpy-1.22.2 pandas-1.4.0 python-dateutil-2.8.2 pytz-2021.3 six-1.16.0 + Removing intermediate container 363ffa40779c + ---> 79f0ed627dd6 + Step 4/4 : CMD [ "python3", "/my-script.py" ] + ---> Running in 4f45fc08e6df + Removing intermediate container 4f45fc08e6df + ---> 4fd169b43c5f + Successfully built 4fd169b43c5f + Successfully tagged prova_4_my_service:latest + Creating prova_4_my_service_1 ... done + ``` diff --git a/docs/compose/hands-on.md b/docs/compose/hands-on.md new file mode 100644 index 0000000..148eb4c --- /dev/null +++ b/docs/compose/hands-on.md @@ -0,0 +1,121 @@ + +### Hands-on 1 + +Write the docker-compose.yml file for the following Docker CLI inserting the `depends_on` condition on db health check + +=== "Exercise details" + ```bash + docker network create wordpress_net + docker volume create db_data + docker volume create wp_data + docker container run --name db \ + --network wordpress_net \ + -v db_data:/var/lib/mysql \ + -e MYSQL_ROOT_PASSWORD=somewordpress \ + -e MYSQL_USER=wordpress_user \ + -e MYSQL_PASSWORD=wordpress_password \ + -e MYSQL_DATABASE=wordpress_db \ + --restart always \ + --health-cmd="mysqladmin ping --silent" \ + --health-interval=10s \ + --health-start-period=10s \ + --health-timeout=10s \ + --health-retries=60 \ + --restart always \ + -d \ + mariadb:10.6.4-focal + + docker run --name wp \ + --network wordpress_net \ + -v wp_data:/var/www/html \ + -p 8080:80 \ + -e WORDPRESS_DB_HOST=db \ + -e WORDPRESS_DB_USER=wordpress_user \ + -e WORDPRESS_DB_PASSWORD=wordpress_password \ + -e WORDPRESS_DB_NAME=wordpress_database \ + -d \ + wordpress + ``` +=== "Solution" + ```yaml + services: + db: + image: mariadb:10.6.4-focal + volumes: + - db_data:/var/lib/mysql + restart: always + environment: + - MYSQL_ROOT_PASSWORD=somewordpress + - MYSQL_DATABASE=wordpress_database + - MYSQL_USER=wordpress_user + - MYSQL_PASSWORD=wordpress_password + healthcheck: + test: ["CMD", "mysqladmin", "ping", "--silent"] + interval: 10s + timeout: 10s + retries: 60 + start_period: 10s + + wordpress: + image: wordpress:latest + volumes: + - wp_data:/var/www/html + ports: + - 8081:80 + restart: always + environment: + - WORDPRESS_DB_HOST=db + - WORDPRESS_DB_USER=wordpress_user + - WORDPRESS_DB_PASSWORD=wordpress_password + - WORDPRESS_DB_NAME=wordpress_database + depends_on: + db: + condition: service_healthy + + volumes: + db_data: + wp_data: + ``` + +### Hands-on 2 + +Write the docker-compose.yml file that builds the following Dockerfile and uses it + +=== "Exercise details" + ``` + base-image: jupyter/minimal-notebook + python module to install: pandas, numpy + expose port: 8888 + command: /opt/conda/bin/python3.11 /opt/conda/bin/jupyter-lab \ + --no-browser \ + --allow-root \ + --NotebookApp.token='' \ + --NotebookApp.password='' + ``` +=== "Solution" + ```bash + mkdir exercise2 + cd exercise2 + cat > requirements.txt << EOF + pandas + numpy + EOF + + cat > Dockerfile << EOF + FROM jupyter/minimal-notebook + COPY requirements.txt /requirements.txt + RUN pip install -r /requirements.txt + EOF + + cat > compose.yaml << EOF + services: + my_jupyter: + build: . + ports: + - 8888:8888 + command: /opt/conda/bin/python3.11 /opt/conda/bin/jupyter-lab --no-browser --allow-root --NotebookApp.token='' --NotebookApp.password='' + EOF + + # To execute the application run: + # docker compose up + ``` \ No newline at end of file diff --git a/docs/container/example.md b/docs/container/example.md index fb5ebe0..9d8bdc5 100644 --- a/docs/container/example.md +++ b/docs/container/example.md @@ -12,32 +12,32 @@ docker search nginx You will get something like the following output: ```bash -NAME DESCRIPTION STARS OFFICIAL AUTOMATED -nginx Official build of Nginx. 18966 [OK] -unit Official build of NGINX Unit: Universal Web … 10 [OK] -nginxinc/nginx-unprivileged Unprivileged NGINX Dockerfiles 118 -nginx/nginx-ingress NGINX and NGINX Plus Ingress Controllers fo… 76 -nginx/nginx-prometheus-exporter NGINX Prometheus Exporter for NGINX and NGIN… 33 -nginx/unit NGINX Unit is a dynamic web and application … 64 -nginxinc/nginx-s3-gateway Authenticating and caching gateway based on … 2 -nginx/nginx-ingress-operator NGINX Ingress Operator for NGINX and NGINX P… 0 -nginxinc/amplify-agent NGINX Amplify Agent docker repository 1 -nginx/nginx-quic-qns NGINX QUIC interop 1 -nginxinc/ingress-demo Ingress Demo 4 -nginxproxy/nginx-proxy Automated Nginx reverse proxy for docker con… 102 -nginxproxy/acme-companion Automated ACME SSL certificate generation fo… 123 -bitnami/nginx Bitnami nginx Docker Image 172 [OK] -bitnami/nginx-ingress-controller Bitnami Docker Image for NGINX Ingress Contr… 29 [OK] -ubuntu/nginx Nginx, a high-performance reverse proxy & we… 98 -nginxinc/nginmesh_proxy_debug 0 -nginxproxy/docker-gen Generate files from docker container meta-da… 12 -kasmweb/nginx An Nginx image based off nginx:alpine and in… 6 -nginxinc/mra-fakes3 0 -rancher/nginx-ingress-controller 11 -nginxinc/ngx-rust-tool 0 -nginxinc/mra_python_base 0 -nginxinc/nginmesh_proxy_init 0 -rancher/nginx-ingress-controller-defaultbackend 2 +NAME DESCRIPTION STARS OFFICIAL +nginx Official build of Nginx. 20157 [OK] +nginx/nginx-quic-qns NGINX QUIC interop 1 +nginx/nginx-ingress NGINX and NGINX Plus Ingress Controllers fo… 94 +nginx/nginx-ingress-operator NGINX Ingress Operator for NGINX and NGINX P… 2 +nginx/nginx-prometheus-exporter NGINX Prometheus Exporter for NGINX and NGIN… 43 +nginx/unit This repository is retired, use the Docker o… 63 +nginx/unit-preview Unit preview features 0 +bitnami/nginx Bitnami container image for NGINX 193 +rapidfort/nginx RapidFort optimized, hardened image for NGINX 15 +kasmweb/nginx An Nginx image based off nginx:alpine and in… 8 +ubuntu/nginx Nginx, a high-performance reverse proxy & we… 116 +chainguard/nginx Minimal Wolfi-based nginx HTTP, reverse prox… 2 +dockette/nginx Nginx SSL / HSTS / HTTP2 3 +jitesoft/nginx Nginx on alpine linux 0 +docksal/nginx Nginx service image for Docksal 0 +gluufederation/nginx A customized NGINX image containing a consu… 1 +okteto/nginx 0 +objectscale/nginx 0 +intel/nginx 0 +circleci/nginx This image is for internal use 2 +bitnamicharts/nginx 0 +vmware/nginx 2 +rancher/nginx 2 +linuxserver/nginx An Nginx container, brought to you by LinuxS… 217 +redash/nginx Pre-configured nginx to proxy linked contain… 2 ``` !!! tip The `docker search` command returns the following image information: @@ -61,14 +61,14 @@ docker image pull nginx ```bash Using default tag: latest latest: Pulling from library/nginx -52d2b7f179e3: Pull complete -fd9f026c6310: Pull complete -055fa98b4363: Pull complete -96576293dd29: Pull complete -a7c4092be904: Pull complete -e3b6889c8954: Pull complete -da761d9a302b: Pull complete -Digest: sha256:104c7c5c54f2685f0f46f3be607ce60da7085da3eaa5ad22d3d9f01594295e9c +e4fff0779e6d: Pull complete +2a0cb278fd9f: Pull complete +7045d6c32ae2: Pull complete +03de31afb035: Pull complete +0f17be8dcff2: Pull complete +14b7e5e8f394: Pull complete +23fa5a7b99a6: Pull complete +Digest: sha256:447a8665cc1dab95b1ca778e162215839ccbb9189104c79d7ec3a81e14577add Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest ``` @@ -81,10 +81,10 @@ docker image ls The output of this command provides useful information, including the size of the image: ```bash -REPOSITORY TAG IMAGE ID CREATED SIZE -nginx latest eea7b3dcba7e 2 weeks ago 187MB -ubuntu latest c6b84b685f35 2 weeks ago 77.8MB -hello-world latest 9c7a54a9a43c 4 months ago 13.3kB +REPOSITORY TAG IMAGE ID CREATED SIZE +nginx latest 5ef79149e0ec 2 weeks ago 188MB +ubuntu latest edbfe74c41f8 4 weeks ago 78.1MB +hello-world latest d2c94e258dcb 16 months ago 13.3kB ``` Let's have a look at the image with the commands we have already seen in the previous section: @@ -93,58 +93,20 @@ Let's have a look at the image with the commands we have already seen in the pre docker image inspect nginx ``` -```bash linenums="1" hl_lines="29 37 61" +```bash linenums="1" hl_lines="30 23 37-39" [ { - "Id": "sha256:eea7b3dcba7ee47c0d16a60cc85d2b977d166be3960541991f3e6294d795ed24", + "Id": "sha256:5ef79149e0ec84a7a9f9284c3f91aa3c20608f8391f5445eabe92ef07dbda03c", "RepoTags": [ "nginx:latest" ], "RepoDigests": [ - "nginx@sha256:104c7c5c54f2685f0f46f3be607ce60da7085da3eaa5ad22d3d9f01594295e9c" + "nginx@sha256:447a8665cc1dab95b1ca778e162215839ccbb9189104c79d7ec3a81e14577add" ], "Parent": "", - "Comment": "", - "Created": "2023-08-16T09:50:55.765544033Z", - "Container": "50b019921f82064e1d8af7e2723929d4c5fafcfd6d8b03595711bd1e455dd3c4", - "ContainerConfig": { - "Hostname": "50b019921f82", - "Domainname": "", - "User": "", - "AttachStdin": false, - "AttachStdout": false, - "AttachStderr": false, - "ExposedPorts": { - "80/tcp": {} - }, - "Tty": false, - "OpenStdin": false, - "StdinOnce": false, - "Env": [ - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - "NGINX_VERSION=1.25.2", - "NJS_VERSION=0.8.0", - "PKG_RELEASE=1~bookworm" - ], - "Cmd": [ - "/bin/sh", - "-c", - "#(nop) ", - "CMD [\"nginx\" \"-g\" \"daemon off;\"]" - ], - "Image": "sha256:d59ed5fe14c2a306f94488f41ddc8fb060312ee31997f5e077a4c4b29b19114e", - "Volumes": null, - "WorkingDir": "", - "Entrypoint": [ - "/docker-entrypoint.sh" - ], - "OnBuild": null, - "Labels": { - "maintainer": "NGINX Docker Maintainers " - }, - "StopSignal": "SIGQUIT" - }, - "DockerVersion": "20.10.23", + "Comment": "buildkit.dockerfile.v0", + "Created": "2024-08-14T21:31:12Z", + "DockerVersion": "", "Author": "", "Config": { "Hostname": "", @@ -161,16 +123,19 @@ docker image inspect nginx "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - "NGINX_VERSION=1.25.2", - "NJS_VERSION=0.8.0", - "PKG_RELEASE=1~bookworm" + "NGINX_VERSION=1.27.1", + "NJS_VERSION=0.8.5", + "NJS_RELEASE=1~bookworm", + "PKG_RELEASE=1~bookworm", + "DYNPKG_RELEASE=2~bookworm" ], "Cmd": [ "nginx", "-g", "daemon off;" ], - "Image": "sha256:d59ed5fe14c2a306f94488f41ddc8fb060312ee31997f5e077a4c4b29b19114e", + "ArgsEscaped": true, + "Image": "", "Volumes": null, "WorkingDir": "", "Entrypoint": [ @@ -184,27 +149,26 @@ docker image inspect nginx }, "Architecture": "amd64", "Os": "linux", - "Size": 186639842, - "VirtualSize": 186639842, + "Size": 187694648, "GraphDriver": { "Data": { - "LowerDir": "/var/lib/docker/overlay2/8072cde78daa76af66dabe39fb661b0faf407786de21649c26fc18a6e1faf6a2/diff:/var/lib/docker/overlay2/4478bca3aabcb4ad7375573863ae4470ccc6aa5dfdbf055d94f881ea364f2da7/diff:/var/lib/docker/overlay2/f982333ae41a3a42a3eb7046e74def02cd1c2e6ddbc5d8bb2966720911f3ce5e/diff:/var/lib/docker/overlay2/e15b9368ef0bf3c0c048c6ca2ae517d3136663880fae208addb20574c9032e64/diff:/var/lib/docker/overlay2/927f8fc9244550a2d1da3449dd58bbdb98bf3d294f094436ac62761790dfaab8/diff:/var/lib/docker/overlay2/edb78366fb60e8316a834b56050484af04954ca588288d8cece3b38f6783fd72/diff", - "MergedDir": "/var/lib/docker/overlay2/511ad049a7c912383723eb26a7112997bf95c2b0033e9effa50fbb21dae974ac/merged", - "UpperDir": "/var/lib/docker/overlay2/511ad049a7c912383723eb26a7112997bf95c2b0033e9effa50fbb21dae974ac/diff", - "WorkDir": "/var/lib/docker/overlay2/511ad049a7c912383723eb26a7112997bf95c2b0033e9effa50fbb21dae974ac/work" + "LowerDir": "/var/lib/docker/overlay2/29bfd1646b549c5a2e7488cd2df0cfbf5b31e6e452390a6419590f798a5be2b7/diff:/var/lib/docker/overlay2/b9732ca651e6793c280fe0b6408bbebe59bbbebbdd596b40cfd51f469243892a/diff:/var/lib/docker/overlay2/2e84243b34f95d37bd725e031f33665c8a2ec89d99824bcb96a0694a52dcb7c9/diff:/var/lib/docker/overlay2/4d59513c75c18791768dc9a21232185999d0fa81c65506e950842b46565fb20b/diff:/var/lib/docker/overlay2/4bd3dd2794ec1e9f2729f9252882a1728abbd44a2e417feb55fbd019857d7054/diff:/var/lib/docker/overlay2/9145ec71e543c915530869f33be035a9f64642f304aa39acdd73b64d6d667d48/diff", + "MergedDir": "/var/lib/docker/overlay2/670ced786458f0d0102c989a939e8808fdfd0e8c982c70d6173b7d7b36fe9e9d/merged", + "UpperDir": "/var/lib/docker/overlay2/670ced786458f0d0102c989a939e8808fdfd0e8c982c70d6173b7d7b36fe9e9d/diff", + "WorkDir": "/var/lib/docker/overlay2/670ced786458f0d0102c989a939e8808fdfd0e8c982c70d6173b7d7b36fe9e9d/work" }, "Name": "overlay2" }, "RootFS": { "Type": "layers", "Layers": [ - "sha256:511780f88f80081112aea1bfdca6c800e1983e401b338e20b2c6e97f384e4299", - "sha256:4713cb24eeff341d0c36343149beba247572a5ff65c2be5b5d9baafb345c7393", - "sha256:d0a62f56ef413f60049bc87e43e60032b2a2ab8d931e15b86ee0286c85ae91a2", - "sha256:8a7e12012e6f60450e6d2d777b2a2c2256d34a0ccd84d605f72cc5329a87c8b8", - "sha256:e161c3f476b5199ab13856c7e190ed12a6562b7be059c7026ae9f594e1abbcaf", - "sha256:6fb960878295b567d25900b590157b976d080340caeaa8bf8c46d38c01b4537d", - "sha256:563c64030925e9016a2329d3a2b7d47b0c90931baf5d2d0aa926c4c8d94ab894" + "sha256:9853575bc4f955c5892dd64187538a6cd02dba6968eba9201854876a7a257034", + "sha256:72db5db515fdd9ae82b759fc207fdfbcc31567c28bb87950abc94ce1d60b2d40", + "sha256:8b87c0c6652495401acfbe029ede84a5f327664770561ba5f8b7fe9149f52dd0", + "sha256:ec1a2ca4ac8784def146544fc7068db06a188d2da4fd7c4e134a76415b8bc1a8", + "sha256:55e54df86207fa772302a6fc1e78eb60bd7e3ebd4f913ef7f5ad668ad69ab64d", + "sha256:f4f00eaedec7933a48b09f3948c685c41d55f0bf5906295dd022c05b65082344", + "sha256:5f0272c6e96d5cd8ea1c6507cfce81980d4b99322bd037d99250a79d4c0b9f1a" ] }, "Metadata": { @@ -214,7 +178,7 @@ docker image inspect nginx ] ``` -We can see that the nginx version in our container will be `1.25.2`, the service will be listening on port `80` and the command that will be executed at the container start is `nginx -g daemon off;`. +We can see that the nginx version in our container will be `1.27.1`, the service will be listening on port `80` and the command that will be executed at the container start is `nginx -g daemon off;`. This is a useful exercise, but in general you will find these information in the [description](https://hub.docker.com/_/nginx?tab=description&page=1&ordering=last_updated){:target=_blank} of the image on Docker hub. @@ -245,7 +209,7 @@ docker container ps ```bash docker container ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -43d8e7c9a160 nginx "/docker-entrypoint.…" 17 seconds ago Up 9 seconds 80/tcp nginx +43147119c02a nginx "/docker-entrypoint.…" 20 seconds ago Up 12 seconds 80/tcp nginx ``` ### Getting the container log @@ -267,14 +231,14 @@ docker container logs nginx /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh /docker-entrypoint.sh: Configuration complete; ready for start up -2023/09/04 08:08:28 [notice] 1#1: using the "epoll" event method -2023/09/04 08:08:28 [notice] 1#1: nginx/1.25.2 -2023/09/04 08:08:28 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14) -2023/09/04 08:08:28 [notice] 1#1: OS: Linux 5.15.0-82-generic -2023/09/04 08:08:28 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576 -2023/09/04 08:08:28 [notice] 1#1: start worker processes -2023/09/04 08:08:28 [notice] 1#1: start worker process 29 -2023/09/04 08:08:28 [notice] 1#1: start worker process 30 +2024/09/04 14:09:50 [notice] 1#1: using the "epoll" event method +2024/09/04 14:09:50 [notice] 1#1: nginx/1.27.1 +2024/09/04 14:09:50 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14) +2024/09/04 14:09:50 [notice] 1#1: OS: Linux 6.8.0-40-generic +2024/09/04 14:09:50 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576 +2024/09/04 14:09:50 [notice] 1#1: start worker processes +2024/09/04 14:09:50 [notice] 1#1: start worker process 29 +2024/09/04 14:09:50 [notice] 1#1: start worker process 30 ``` !!! tip @@ -289,9 +253,9 @@ We can inspect the processes running inside our container using the `docker cont ```bash docker container top nginx UID PID PPID C STIME TTY TIME CMD -root 4989 4969 0 08:08 ? 00:00:00 nginx: master process nginx -g daemon off; -systemd+ 5035 4989 0 08:08 ? 00:00:00 nginx: worker process -systemd+ 5036 4989 0 08:08 ? 00:00:00 nginx: worker process +root 49252 49232 0 14:09 ? 00:00:00 nginx: master process nginx -g daemon off; +message+ 49301 49252 0 14:09 ? 00:00:00 nginx: worker process +message+ 49302 49252 0 14:09 ? 00:00:00 nginx: worker process ``` ### Finding out more about our container @@ -309,8 +273,8 @@ Let's use again the command `docker container inspect` to get more information a ```bash [ { - "Id": "43d8e7c9a160a792bb7b9e85fd589c2986504edc0a8f7698473648dd71ee8810", - "Created": "2023-09-04T08:08:19.846675755Z", + "Id": "43147119c02a544cffcc2e99a2bd634b6fcec63406e4d9ac510821f5cf140e60", + "Created": "2024-09-04T14:09:42.284257833Z", "Path": "/docker-entrypoint.sh", "Args": [ "nginx", @@ -324,17 +288,17 @@ Let's use again the command `docker container inspect` to get more information a "Restarting": false, "OOMKilled": false, "Dead": false, - "Pid": 4989, + "Pid": 49252, "ExitCode": 0, "Error": "", - "StartedAt": "2023-09-04T08:08:27.030292632Z", + "StartedAt": "2024-09-04T14:09:49.261329401Z", "FinishedAt": "0001-01-01T00:00:00Z" }, - "Image": "sha256:eea7b3dcba7ee47c0d16a60cc85d2b977d166be3960541991f3e6294d795ed24", - "ResolvConfPath": "/var/lib/docker/containers/43d8e7c9a160a792bb7b9e85fd589c2986504edc0a8f7698473648dd71ee8810/resolv.conf", - "HostnamePath": "/var/lib/docker/containers/43d8e7c9a160a792bb7b9e85fd589c2986504edc0a8f7698473648dd71ee8810/hostname", - "HostsPath": "/var/lib/docker/containers/43d8e7c9a160a792bb7b9e85fd589c2986504edc0a8f7698473648dd71ee8810/hosts", - "LogPath": "/var/lib/docker/containers/43d8e7c9a160a792bb7b9e85fd589c2986504edc0a8f7698473648dd71ee8810/43d8e7c9a160a792bb7b9e85fd589c2986504edc0a8f7698473648dd71ee8810-json.log", + "Image": "sha256:5ef79149e0ec84a7a9f9284c3f91aa3c20608f8391f5445eabe92ef07dbda03c", + "ResolvConfPath": "/var/lib/docker/containers/43147119c02a544cffcc2e99a2bd634b6fcec63406e4d9ac510821f5cf140e60/resolv.conf", + "HostnamePath": "/var/lib/docker/containers/43147119c02a544cffcc2e99a2bd634b6fcec63406e4d9ac510821f5cf140e60/hostname", + "HostsPath": "/var/lib/docker/containers/43147119c02a544cffcc2e99a2bd634b6fcec63406e4d9ac510821f5cf140e60/hosts", + "LogPath": "/var/lib/docker/containers/43147119c02a544cffcc2e99a2bd634b6fcec63406e4d9ac510821f5cf140e60/43147119c02a544cffcc2e99a2bd634b6fcec63406e4d9ac510821f5cf140e60-json.log", "Name": "/nginx", "RestartCount": 0, "Driver": "overlay2", @@ -350,7 +314,7 @@ Let's use again the command `docker container inspect` to get more information a "Type": "json-file", "Config": {} }, - "NetworkMode": "default", + "NetworkMode": "bridge", "PortBindings": {}, "RestartPolicy": { "Name": "no", @@ -360,8 +324,8 @@ Let's use again the command `docker container inspect` to get more information a "VolumeDriver": "", "VolumesFrom": null, "ConsoleSize": [ - 60, - 281 + 39, + 178 ], "CapAdd": null, "CapDrop": null, @@ -409,7 +373,7 @@ Let's use again the command `docker container inspect` to get more information a "MemorySwappiness": null, "OomKillDisable": null, "PidsLimit": null, - "Ulimits": null, + "Ulimits": [], "CpuCount": 0, "CpuPercent": 0, "IOMaximumIOps": 0, @@ -424,7 +388,8 @@ Let's use again the command `docker container inspect` to get more information a "/proc/timer_stats", "/proc/sched_debug", "/proc/scsi", - "/sys/firmware" + "/sys/firmware", + "/sys/devices/virtual/powercap" ], "ReadonlyPaths": [ "/proc/bus", @@ -436,16 +401,16 @@ Let's use again the command `docker container inspect` to get more information a }, "GraphDriver": { "Data": { - "LowerDir": "/var/lib/docker/overlay2/1485063bd2a8e353b620248832fdae8836b6050e9499d293d1b65c5608a0433f-init/diff:/var/lib/docker/overlay2/511ad049a7c912383723eb26a7112997bf95c2b0033e9effa50fbb21dae974ac/diff:/var/lib/docker/overlay2/8072cde78daa76af66dabe39fb661b0faf407786de21649c26fc18a6e1faf6a2/diff:/var/lib/docker/overlay2/4478bca3aabcb4ad7375573863ae4470ccc6aa5dfdbf055d94f881ea364f2da7/diff:/var/lib/docker/overlay2/f982333ae41a3a42a3eb7046e74def02cd1c2e6ddbc5d8bb2966720911f3ce5e/diff:/var/lib/docker/overlay2/e15b9368ef0bf3c0c048c6ca2ae517d3136663880fae208addb20574c9032e64/diff:/var/lib/docker/overlay2/927f8fc9244550a2d1da3449dd58bbdb98bf3d294f094436ac62761790dfaab8/diff:/var/lib/docker/overlay2/edb78366fb60e8316a834b56050484af04954ca588288d8cece3b38f6783fd72/diff", - "MergedDir": "/var/lib/docker/overlay2/1485063bd2a8e353b620248832fdae8836b6050e9499d293d1b65c5608a0433f/merged", - "UpperDir": "/var/lib/docker/overlay2/1485063bd2a8e353b620248832fdae8836b6050e9499d293d1b65c5608a0433f/diff", - "WorkDir": "/var/lib/docker/overlay2/1485063bd2a8e353b620248832fdae8836b6050e9499d293d1b65c5608a0433f/work" + "LowerDir": "/var/lib/docker/overlay2/2439f7d82ca5c505d4b56fde68aa78ba7caf71b3ca2cf1598dddff528566a964-init/diff:/var/lib/docker/overlay2/670ced786458f0d0102c989a939e8808fdfd0e8c982c70d6173b7d7b36fe9e9d/diff:/var/lib/docker/overlay2/29bfd1646b549c5a2e7488cd2df0cfbf5b31e6e452390a6419590f798a5be2b7/diff:/var/lib/docker/overlay2/b9732ca651e6793c280fe0b6408bbebe59bbbebbdd596b40cfd51f469243892a/diff:/var/lib/docker/overlay2/2e84243b34f95d37bd725e031f33665c8a2ec89d99824bcb96a0694a52dcb7c9/diff:/var/lib/docker/overlay2/4d59513c75c18791768dc9a21232185999d0fa81c65506e950842b46565fb20b/diff:/var/lib/docker/overlay2/4bd3dd2794ec1e9f2729f9252882a1728abbd44a2e417feb55fbd019857d7054/diff:/var/lib/docker/overlay2/9145ec71e543c915530869f33be035a9f64642f304aa39acdd73b64d6d667d48/diff", + "MergedDir": "/var/lib/docker/overlay2/2439f7d82ca5c505d4b56fde68aa78ba7caf71b3ca2cf1598dddff528566a964/merged", + "UpperDir": "/var/lib/docker/overlay2/2439f7d82ca5c505d4b56fde68aa78ba7caf71b3ca2cf1598dddff528566a964/diff", + "WorkDir": "/var/lib/docker/overlay2/2439f7d82ca5c505d4b56fde68aa78ba7caf71b3ca2cf1598dddff528566a964/work" }, "Name": "overlay2" }, "Mounts": [], "Config": { - "Hostname": "43d8e7c9a160", + "Hostname": "43147119c02a", "Domainname": "", "User": "", "AttachStdin": false, @@ -459,9 +424,11 @@ Let's use again the command `docker container inspect` to get more information a "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - "NGINX_VERSION=1.25.2", - "NJS_VERSION=0.8.0", - "PKG_RELEASE=1~bookworm" + "NGINX_VERSION=1.27.1", + "NJS_VERSION=0.8.5", + "NJS_RELEASE=1~bookworm", + "PKG_RELEASE=1~bookworm", + "DYNPKG_RELEASE=2~bookworm" ], "Cmd": [ "nginx", @@ -482,17 +449,17 @@ Let's use again the command `docker container inspect` to get more information a }, "NetworkSettings": { "Bridge": "", - "SandboxID": "0f0dc6953649e1d30c725332e4071257dd750addd46a6c0aa0c6e77a96e31364", - "HairpinMode": false, - "LinkLocalIPv6Address": "", - "LinkLocalIPv6PrefixLen": 0, + "SandboxID": "4c76fb8e97c6aca6858a8476d764d259fbebbb97c38b48f6b65a8bd8413eb165", + "SandboxKey": "/var/run/docker/netns/4c76fb8e97c6", "Ports": { "80/tcp": null }, - "SandboxKey": "/var/run/docker/netns/0f0dc6953649", + "HairpinMode": false, + "LinkLocalIPv6Address": "", + "LinkLocalIPv6PrefixLen": 0, "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, - "EndpointID": "25e03f10335ea9356d88ad67ed999291d6c6e26c3f91a1fd8853772a3988604f", + "EndpointID": "cbfee38857162451d749c7772167ac9d01c9fb844b76211aa41c0b239b384472", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, @@ -505,16 +472,17 @@ Let's use again the command `docker container inspect` to get more information a "IPAMConfig": null, "Links": null, "Aliases": null, - "NetworkID": "6e452f5b4a2bc0f04db8a0393f0346a1a6852379c7443adb20cbb5a05b3c52bf", - "EndpointID": "25e03f10335ea9356d88ad67ed999291d6c6e26c3f91a1fd8853772a3988604f", + "MacAddress": "02:42:ac:11:00:03", + "DriverOpts": null, + "NetworkID": "b6fbe659163bbccd7ffdace6cfe009584c698941994079fe9f9b3a34d360839c", + "EndpointID": "cbfee38857162451d749c7772167ac9d01c9fb844b76211aa41c0b239b384472", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.3", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, - "MacAddress": "02:42:ac:11:00:03", - "DriverOpts": null + "DNSNames": null } } } @@ -531,8 +499,5 @@ docker container inspect -f '{{.NetworkSettings.IPAddress}}' nginx ``` ``` -172.17.0.2 +172.17.0.3 ``` - - - diff --git a/docs/container/health_checks.md b/docs/container/health_checks.md index 563aea9..bae0030 100644 --- a/docs/container/health_checks.md +++ b/docs/container/health_checks.md @@ -169,7 +169,7 @@ The container is flagged as unhealthy after three failures of the check (you can -e MYSQL_USER=${MYSQL_USER} \ -e MYSQL_PASSWORD=${MYSQL_PASSWORD} \ -e MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \ - --health-cmd='mysqladmin -p${MYSQL_ROOT_PASSWORD} ping -h localhost' \ + --health-cmd='mariadb-admin -p${MYSQL_ROOT_PASSWORD} ping -h localhost' \ --health-interval=20s \ --health-retries=3 \ mariadb:latest diff --git a/docs/container/manipulation.md b/docs/container/manipulation.md index 614d239..58fedf6 100644 --- a/docs/container/manipulation.md +++ b/docs/container/manipulation.md @@ -8,10 +8,10 @@ Let's see what happens: ```bash Unable to find image 'ubuntu:latest' locally latest: Pulling from library/ubuntu -445a6a12be2b: Pull complete -Digest: sha256:aabed3296a3d45cede1dc866a24476c4d7e093aa806263c27ddaadbdce3c1054 +31e907dcc94a: Pull complete +Digest: sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04e34a9ab63ee Status: Downloaded newer image for ubuntu:latest -root@2c8a2962ca5c:/# +root@0e539c9ccee4:/# ``` We are inside the docker container! @@ -26,8 +26,8 @@ We are inside the docker container! This is a fully fledged Ubuntu host, and we can do anything we like in it. Let's explore it a bit, starting with asking for its hostname: ```bash -root@2c8a2962ca5c:/# hostname -2c8a2962ca5c +root@0e539c9ccee4:/# hostname +0e539c9ccee4 ``` !!! tip @@ -35,23 +35,25 @@ root@2c8a2962ca5c:/# hostname Let's have a look at the `/etc/hosts` file too. ```bash -root@2c8a2962ca5c:/# cat /etc/hosts +root@0e539c9ccee4:/# cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters -172.17.0.2 2c8a2962ca5c +172.17.0.2 0e539c9ccee4 ``` Docker has also added a host entry for our container with its IP address. Let's also check out its networking configuration. ```bash -root@2c8a2962ca5c:/# ip a +root@0e539c9ccee4:/# ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever + inet6 ::1/128 scope host + valid_lft forever preferred_lft forever 6: eth0@if7: mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 @@ -68,10 +70,10 @@ As we can see, we have the `lo` loopback interface and the `eth0@if7` network in We can also check its running processes: ```bash -root@2c8a2962ca5c:/# ps aux +root@0e539c9ccee4:/# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND -root 1 0.0 0.0 4624 3780 pts/0 Ss 07:43 0:00 bash -root 352 0.0 0.0 7060 1568 pts/0 R+ 07:53 0:00 ps aux +root 1 0.0 0.0 4588 3968 pts/0 Ss 11:04 0:00 bash +root 334 0.0 0.1 7888 4224 pts/0 R+ 11:08 0:00 ps aux ``` Note that the process `bash` has PID 1. @@ -83,15 +85,15 @@ So the container still exists but it's stopped: ```bash docker container ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -2c8a2962ca5c ubuntu "bash" 11 minutes ago Exited (0) 13 seconds ago magical_sanderson -3a3eb75d3da3 hello-world "/hello" 22 minutes ago Exited (0) 22 minutes ago sharp_kepler +0e539c9ccee4 ubuntu "bash" 5 minutes ago Exited (0) 15 seconds ago frosty_satoshi +a621c49ed3d6 hello-world "/hello" 15 minutes ago Exited (0) 15 minutes ago bold_galileo ``` ### Starting a stopped container We can start again our stopped container with `docker container start `: ```bash -docker container start 2c8a2962ca5c -2c8a2962ca5c +docker container start 0e539c9ccee4 +0e539c9ccee4 ``` Our container will restart with the same options we had specified when we launched it with the `docker run` command. @@ -108,8 +110,8 @@ This is useful when you want to see what is written in the standard output in re So running the `attach` command on our Ubuntu container will bring us back to our bash prompt: ```bash -docker container attach 2c8a2962ca5c -root@2c8a2962ca5c:/# +docker attach 0e539c9ccee4 +root@0e539c9ccee4:/# ``` You can detach from a container and leave it running using the `CTRL-p CTRL-q` key sequence. @@ -124,16 +126,16 @@ The command can be run in background using the option `-d` or interactively usin Try the following command on your Ubuntu container: ```bash -docker exec -it 2c8a2962ca5c bash -root@2c8a2962ca5c:/# +docker exec -it 0e539c9ccee4 bash +root@0e539c9ccee4:/# ``` Let's look at the processes inside the container: ```bash -root@2c8a2962ca5c:/# ps aux +root@0e539c9ccee4:/# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND -root 1 0.0 0.0 4624 3844 pts/0 Ss+ 07:55 0:00 bash -root 9 0.0 0.0 4624 3788 pts/1 Ss 07:59 0:00 bash -root 17 0.0 0.0 7060 1572 pts/1 R+ 07:59 0:00 ps aux +root 1 0.0 0.0 4588 3712 pts/0 Ss+ 13:56 0:00 bash +root 9 0.1 0.0 4588 3968 pts/1 Ss 13:57 0:00 bash +root 17 0.0 0.1 7888 4096 pts/1 R+ 13:57 0:00 ps aux ``` We can see that the `exec` command started a new shell session. diff --git a/docs/image/automation/exercises.md b/docs/image/automation/exercises.md deleted file mode 100644 index 9ed9cec..0000000 --- a/docs/image/automation/exercises.md +++ /dev/null @@ -1,8 +0,0 @@ -# Exercise: Create a pipeline to periodically build your latest tag - -HandsOn live - -# Exercise: push image to dockerHUB instead - -HandsOn live -~ diff --git a/docs/image/automation/ghaction.md b/docs/image/automation/ghaction.md new file mode 100644 index 0000000..e632d3a --- /dev/null +++ b/docs/image/automation/ghaction.md @@ -0,0 +1,106 @@ +## Create a New Repository on GitHub + +1. Go to GitHub and log in to your account. +2. Click the `+` icon in the top right corner and select `New repository`. +3. Fill out the repository name and description, then click `Create repository`. + +## Add GitHub as a Remote + +Add your newly created GitHub repository as a remote: + +``` +git remote add github https://github.com/username/repository-name.git +``` + +## Create a GitHub Personal Access Token: + +1. Go to GitHub [Personal Access Tokens](https://github.com/settings/tokens). +2. Click `Generate new token`. +3. Add a note, select the `repo` scope for full control of private repositories, and any other necessary scopes. +4. Click `Generate token` and copy the token. This will be used as your GitHub authentication token. + +## Push Your Repository to GitHub + +Push your repository’s branches to GitHub: + +``` +git push github --all +``` + +## Create a GitHub Action to Build and Push Docker Images + +In your GitHub repository, create the necessary directory for GitHub Actions workflows: + +``` +mkdir -p .github/workflows +``` + +Create a new file in the `.github/workflows` directory, e.g., `build-and-push.yml`: + +``` +name: Build and push docker image to Docker Hub + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + + workflow_dispatch: + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v4 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - + name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Docker meta + id: docker_meta + uses: crazy-max/ghaction-docker-meta@v2 + with: + images: ${{ secrets.DOCKERHUB_USERNAME }}/slat + tags: | + type=sha + type=semver,pattern={{raw}} + type=ref,event=branch + - + name: Build & Push image + uses: docker/build-push-action@v2 + with: + context: . + file: Dockerfile + push: true + tags: ${{ steps.docker_meta.outputs.tags }} + labels: ${{ steps.docker_meta.outputs.labels }} +``` + +## Add Secrets to Your GitHub Repository: + +- Go to your GitHub repository and navigate to `Settings`. +- Select `Secrets and variables` → `Actions`. +- Click `New repository secret` and add the following secrets: + * `DOCKERHUB_USERNAME`: Your Docker Hub username. + * `DOCKERHUB_PASSWORD`: Your Docker Hub password or access token. + +## Commit and Push the Workflow File + +Add, commit, and push the workflow file to your GitHub repository: + +``` +git add .github/workflows/build-and-push.yml +git commit -m "Add GitHub Actions workflow for Docker build and push" +git push +``` + + diff --git a/docs/image/automation/index.md b/docs/image/automation/index.md index e8d1acb..7c377ee 100644 --- a/docs/image/automation/index.md +++ b/docs/image/automation/index.md @@ -5,8 +5,8 @@ In this section you'll learn how to leverage CI/CD pipilines in INFN baltig (or - baltig.infn.it account and access - gitlab CLI: ````bash - wget https://gitlab.com/gitlab-org/cli/-/releases/v1.32.0/downloads/glab_1.32.0_Linux_x86_64.deb - sudo dpkg -i glab_1.32.0_Linux_x86_64.deb + wget https://gitlab.com/gitlab-org/cli/-/releases/v1.46.0/downloads/glab_1.46.0_Linux_x86_64.deb + sudo dpkg -i glab_1.46.0_Linux_x86_64.deb ```` - a baltig token with 'api' and 'write_repository' scopes (see below) - having followed the [previous](../dockerfile/exercise.md) tutorial @@ -107,105 +107,10 @@ Once completed you should be able to see the docker image stored on gitlab regis The container is now ready to be pulled from the registry via: `docker pull baltig.infn.it:4567/ciangottini/tutorial-ci` -## Dagger.io preview -- Install the [CLI](https://docs.dagger.io/quickstart/729236/cli#install-the-dagger-cli) and the [SDK](https://docs.dagger.io/quickstart/628381/sdk) via pip3, as they are needed to test the pipeline locally. -- Then create a file in `ci/main.py` with the example code doing the following: - - build the flask image - - instantiate a webserver for tests - - test the response correctness - - publish the image - -```python -import random -import sys +## Exercises -import anyio -import httpx +- Create a pipeline to periodically build your latest tag -import json +- Push image to dockerHUB instead -import anyio -import dagger - - -async def main(): - config = dagger.Config(log_output=sys.stdout) - - async with dagger.Connection(config) as client: - # set build context - context_dir = client.host().directory(".") - - # build using Dockerfile - container = ( - await context_dir.docker_build() - ) - - # execute the container as a service to be tested against - http_srv = ( - container.with_env_variable(name="ENVIRONMENT", value="dagger-test") - .with_env_variable(name="PORT", value="8080") - .with_exposed_port(8080) - .as_service() - ) - - # expose HTTP service to host - tunnel = await client.host().tunnel(http_srv).start() - - # get HTTP service address - endpoint = await tunnel.endpoint() - - # access HTTP service from host - async with httpx.AsyncClient() as http: - r = await http.get(f"http://{endpoint}") - print(r.status_code) - print(r.text) - - result = json.loads(r.text) - expected = {"env":"dagger-test"} - if r.status_code==200 and result==expected: - pass - elif result==expected: - print(f"{result}!={expected}") - sys.exit(1) - else: - print(f"Status code: {r.status_code}") - sys.exit(1) - - image_ref = await container.publish(f"baltig.infn.it:4567/ciangottini/tutorial-ci-23/hello-dagger-{random.randint(0, 10000000)}") - - print(f"Published image to: {image_ref}") - - - -anyio.run(main) -``` - -You can easily try locally the whole chain with: - -```bash -dagger run python ci/main.py -``` - -And just as easily integrate it into a gitlab pipeline with the following content to be appended into `.gitlab-ci.yml`: - -```yaml -.docker: - image: python:3-alpine - services: - - docker:dind -.dagger: - extends: [.docker] - before_script: - - apk add docker-cli curl - - cd /usr/local && { curl -L https://dl.dagger.io/dagger/install.sh | sh; cd -; } - - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} baltig.infn.it:4567 -build-deploy: - extends: [.dagger] - script: - - apk add python3-dev gcc libc-dev - - pip install --upgrade pip && pip install dagger-io httpx - - dagger run python ci/main.py -``` - -For more details and examples visit the [Dagger.io](https://docs.dagger.io/quickstart/593914/hello) documentation diff --git a/docs/image/dockerfile/copy.md b/docs/image/dockerfile/copy.md index bed92a9..c7ae8da 100644 --- a/docs/image/dockerfile/copy.md +++ b/docs/image/dockerfile/copy.md @@ -12,6 +12,8 @@ In the following simple example we want to build a container that compiles a bas Example, a hello.c: ```c +#include + int main () { puts("Hello, world!"); return 0; diff --git a/docs/intro/hello-world.md b/docs/intro/hello-world.md index 8fd277f..0cf2395 100644 --- a/docs/intro/hello-world.md +++ b/docs/intro/hello-world.md @@ -9,8 +9,8 @@ Look at the output: ```bash Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world -719385e32844: Pull complete -Digest: sha256:dcba6daec718f547568c562956fa47e1b03673dd010fe6ee58ca806767031d1c +c1ec31eb5944: Pull complete +Digest: sha256:53cc4d415d839c98be39331c948609b659ed725170ad2ca8eb36951288f81b75 Status: Downloaded newer image for hello-world:latest Hello from Docker! diff --git a/docs/intro/images.md b/docs/intro/images.md index af3b46f..3c1c01f 100644 --- a/docs/intro/images.md +++ b/docs/intro/images.md @@ -3,20 +3,18 @@ The storage location of Docker images and containers depends on the operating sy On Ubuntu, Docker stores images and containers files under `/var/lib/docker`: ```bash -total 52 -drwxr-xr-x 39 root root 4096 Sep 4 07:24 .. -drwx------ 2 root root 4096 Sep 4 07:24 runtimes -drwx-----x 2 root root 4096 Sep 4 07:24 volumes -drwx------ 4 root root 4096 Sep 4 07:24 plugins --rw------- 1 root root 36 Sep 4 07:24 engine-id -drwx------ 3 root root 4096 Sep 4 07:24 image -drwxr-x--- 3 root root 4096 Sep 4 07:24 network -drwx------ 2 root root 4096 Sep 4 07:24 swarm -drwx--x--- 12 root root 4096 Sep 4 07:24 . -drwx--x--x 4 root root 4096 Sep 4 07:24 buildkit -drwx------ 2 root root 4096 Sep 4 07:31 tmp -drwx--x--- 6 root root 4096 Sep 4 07:31 overlay2 -drwx--x--- 3 root root 4096 Sep 4 07:31 containers +total 44 +drwx--x--x 4 root root 4096 Sep 4 10:46 buildkit +drwx--x--- 3 root root 4096 Sep 4 10:53 containers +-rw------- 1 root root 36 Sep 4 10:46 engine-id +drwx------ 3 root root 4096 Sep 4 10:46 image +drwxr-x--- 3 root root 4096 Sep 4 10:46 network +drwx--x--- 6 root root 4096 Sep 4 10:53 overlay2 +drwx------ 4 root root 4096 Sep 4 10:46 plugins +drwx------ 2 root root 4096 Sep 4 10:46 runtimes +drwx------ 2 root root 4096 Sep 4 10:46 swarm +drwx------ 2 root root 4096 Sep 4 10:53 tmp +drwx-----x 2 root root 4096 Sep 4 10:46 volumes ``` Docker images are stored in `/var/lib/docker/overlay2`. @@ -35,16 +33,16 @@ docker image inspect hello-world ```bash [ { - "Id": "sha256:9c7a54a9a43cca047013b82af109fe963fde787f63f9e016fdc3384500c2823d", + "Id": "sha256:d2c94e258dcb3c5ac2798d32e1249e42ef01cba4841c2234249495f87264ac5a", "RepoTags": [ "hello-world:latest" ], .... "GraphDriver": { "Data": { - "MergedDir": "/var/lib/docker/overlay2/04635df94f3219c431d9dfba92f4456f5e0247b3dcc0b94f55d331d4c3ced400/merged", - "UpperDir": "/var/lib/docker/overlay2/04635df94f3219c431d9dfba92f4456f5e0247b3dcc0b94f55d331d4c3ced400/diff", - "WorkDir": "/var/lib/docker/overlay2/04635df94f3219c431d9dfba92f4456f5e0247b3dcc0b94f55d331d4c3ced400/work" + "MergedDir": "/var/lib/docker/overlay2/7fea1105b18fd2b9fb8237cd6ff7bf2e2ba1521012006625ef2b1542e9b5f285/merged", + "UpperDir": "/var/lib/docker/overlay2/7fea1105b18fd2b9fb8237cd6ff7bf2e2ba1521012006625ef2b1542e9b5f285/diff", + "WorkDir": "/var/lib/docker/overlay2/7fea1105b18fd2b9fb8237cd6ff7bf2e2ba1521012006625ef2b1542e9b5f285/work" }, "Name": "overlay2" }, @@ -62,11 +60,11 @@ The `hello-world` image therefore contains just one layer that adds the `hello` Look at the content of the **UpperDir**: ```bash -sudo ls -latr /var/lib/docker/overlay2/04635df94f3219c431d9dfba92f4456f5e0247b3dcc0b94f55d331d4c3ced400/diff +sudo ls -latr /var/lib/docker/overlay2/7fea1105b18fd2b9fb8237cd6ff7bf2e2ba1521012006625ef2b1542e9b5f285/diff total 24 --rwxrwxr-x 1 root root 13256 May 4 17:36 hello -drwxr-xr-x 2 root root 4096 Sep 4 07:31 . -drwx--x--- 3 root root 4096 Sep 4 07:31 .. +-rwxr-xr-x 1 root root 13256 Dec 15 2023 hello +drwxr-xr-x 2 root root 4096 Sep 4 10:53 . +drwx--x--- 3 root root 4096 Sep 4 10:53 .. ``` Another interesting command is `docker history` that shows the hystory of an image. Try it! @@ -77,9 +75,9 @@ docker history hello-world Output: ```bash -IMAGE CREATED CREATED BY SIZE COMMENT -9c7a54a9a43c 4 months ago /bin/sh -c #(nop) CMD ["/hello"] 0B - 4 months ago /bin/sh -c #(nop) COPY file:201f8f1849e89d53… 13.3kB +IMAGE CREATED CREATED BY SIZE COMMENT +d2c94e258dcb 16 months ago CMD ["/hello"] 0B buildkit.dockerfile.v0 + 16 months ago COPY hello / # buildkit 13.3kB buildkit.dockerfile.v0 ``` Again, you can see here that the image has only one layer (0B lines are neglected). diff --git a/docs/intro/info.md b/docs/intro/info.md index a38fe48..1da2862 100644 --- a/docs/intro/info.md +++ b/docs/intro/info.md @@ -9,15 +9,15 @@ You will get something like the following output: ```bash linenums="1" hl_lines="19 30 31 32 53" Client: Docker Engine - Community - Version: 24.0.5 + Version: 27.2.0 Context: default Debug Mode: false Plugins: buildx: Docker Buildx (Docker Inc.) - Version: v0.11.2 + Version: v0.16.2 Path: /usr/libexec/docker/cli-plugins/docker-buildx compose: Docker Compose (Docker Inc.) - Version: v2.20.2 + Version: v2.29.2 Path: /usr/libexec/docker/cli-plugins/docker-compose Server: @@ -26,7 +26,7 @@ Server: Paused: 0 Stopped: 0 Images: 0 - Server Version: 24.0.5 + Server Version: 27.2.0 Storage Driver: overlay2 Backing Filesystem: extfs Supports d_type: true @@ -39,27 +39,27 @@ Server: Plugins: Volume: local Network: bridge host ipvlan macvlan null overlay - Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog + Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog Swarm: inactive - Runtimes: io.containerd.runc.v2 runc + Runtimes: runc io.containerd.runc.v2 Default Runtime: runc Init Binary: docker-init - containerd version: 8165feabfdfe38c65b599c4993d227328c231fca - runc version: v1.1.8-0-g82f18fe + containerd version: 472731909fa34bd7bc9c087e4c27943f9835f111 + runc version: v1.1.13-0-g58aa920 init version: de40ad0 Security Options: apparmor seccomp Profile: builtin cgroupns - Kernel Version: 5.15.0-82-generic - Operating System: Ubuntu 22.04.3 LTS + Kernel Version: 6.8.0-40-generic + Operating System: Ubuntu 24.04 LTS OSType: linux Architecture: x86_64 CPUs: 2 - Total Memory: 3.82GiB + Total Memory: 3.824GiB Name: tutorvm-1 - ID: 3a17473f-fe4f-4756-85c9-d451843df056 + ID: 56833310-4f20-4141-9869-f6ff1e988f66 Docker Root Dir: /var/lib/docker Debug Mode: false Experimental: false diff --git a/docs/intro/install.md b/docs/intro/install.md index 1f59623..7badbee 100644 --- a/docs/intro/install.md +++ b/docs/intro/install.md @@ -1,4 +1,4 @@ -We will install docker engine on our Ubuntu Jammy 22.04 (LTS) Virtual Machine using the repository. +We will install docker engine on our Ubuntu Noble 24.04 (LTS) Virtual Machine using the repository. !!! info Full instructions are available at [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/) @@ -61,7 +61,7 @@ sudo usermod -aG docker $USER ``` === "Example output" ``` - Docker version 24.0.5, build ced0996 + Docker version 27.2.0, build 3ab4256 ``` diff --git a/mkdocs.yml b/mkdocs.yml index 9ed444c..3bf464c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -65,7 +65,10 @@ nav: - CI/CD build automation: - How to use Gitlab CI/CD to build your image automatically: 'image/automation/index.md' - Use your own runner from a dedicated VM: 'image/automation/runner.md' - - Exercises: 'image/automation/exercises.md' + - How to use Github actions to build your image automatically: 'image/automation/ghaction.md' + - Multi-container applications with Docker Compose: + - Concepts: 'compose/concepts.md' + - Hands-on: 'compose/hands-on.md' -copyright: Copyright © 2022 INFN +copyright: Copyright © 2024 INFN