Skip to content

Compose

Hi ha moltes aplicacions que no poden funcionar soles, sinó que necessiten altres aplicacions per funcionar.

Per exemple el Wordpress necessita una base de dades.

Crea un carpeta cluster i dins d’aquesta carpeta un fitxer docker-compose.yml.

Terminal window
$ mkdir cluster
$ cd cluster
$ nano docker-compose.yml

A continuació tens el contingut del fitxer en format {% link “/tool/yaml/” %}:

services:
apache:
image: httpd:2.4
ports:
- 80:80
  • Pots veure que el fitxer defineix un conjunt de serveis.

  • Cada servei te un nom, en aquest cas apache, que es farà servir per donar nom al contenidor.

  • A continuació per cada servei has de dir quina imatge es farà servir i definir els “port forward” pertinents.

Amb docker compose pots arrencar els contenidors definits perl fitxer docker-compose.yaml amb aquesta ordre:

Terminal window
$ docker compose up -d
Creating network "cluster_default" with the default driver
Pulling apache (httpd:2.4)...
...
Creating cluster_apache_1 ... done

Pots veure que es crea una xarxa amb el nom cluster_default i un contenidor amb el nom cluster_apache_1.

Per defecte, Docker Compose afegeix el nom de la carpeta on està el fitxer docker-compose.yml com a prefix de tots els recursos que crea, en aquest cas cluster_.

Pots verificar que s’ha creat la xarxa:

Terminal window
$ docker network ls | grep cluster
49fca8deb35b cluster_default bridge local

Que és correspon a una interfície de xarxa virtual (fan servir el mateix id):

Terminal window
$ ip -brief addr | grep 49f
br-49fca8deb35b UP 172.18.0.1/16 fe80::42:76ff:fe7e:e33d/64

I que el contenidor està en la xarxa 172.18.0.1/16:

Terminal window
$ docker exec cluster_apache_1 more /etc/hosts | grep 172
172.18.0.2 6ce60b066200

✅ Docker Compose crea una xarxa privada que permet a un conjunt de contenidors estar connectats de manera aïllada del reste d’aplicacions que s’estan executant a la màquina.

Un fitxer docker-compose.yml et permet definir un conjunt de serveis.

Un servei és una aplicació que s’està executant dins un contenidor i que pot ser accedida per qualsevol altre aplicació que tingui accés a la xarxa privada en que està el contenidor.

Modifica el fitxer docker-compose.yml amb tres serveis apache:

services:
apache_1:
image: httpd:2.4
ports:
- 81:81
apache_2:
image: httpd:2.4
ports:
- 82:80
apache_3:
image: httpd:2.4
ports:
- 83:80

Desplega aquesta nova configuració:

Terminal window
$ docker compose up -d
WARNING: Found orphan containers (cluster_apache_1) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.
Creating cluster_apache_3_1 ... done
Creating cluster_apache_2_1 ... done
Creating cluster_apache_1_1 ... done

Pots veure que docker arrencar 3 contenidors, però no elimina el que està en execució.

Un contenidor pot guardar estat (fitxers modificats, dades, etc.) i si elimines el contenidor aquestes estat es perd.

Per tant, per defecte, docker es conservador per evitar que sense voler facis el que no havies de fer:

Terminal window
{% raw %}docker ps -a --format "table {{.ID}}\t{{.Names}}\t{{.Status}}" {% endraw %}
CONTAINER ID NAMES STATUS
8ae4c9a9b99e cluster_apache_1_1 Up 16 seconds
576213c0c870 cluster_apache_3_1 Up 16 seconds
a242c257b255 cluster_apache_2_1 Up 16 seconds
0b092e9e2196 cluster_apache_1 Up 4 minutes

✅ Amb l’opció --format podem limitar la informació que ens mostra l’ordre docker ps`.

Verifica amb nmapque els 4 contenidors estan escoltant als ports respectius:

Terminal window
$ nmap -p80-83 127.0.0.1
...
PORT STATE SERVICE
80/tcp open http
81/tcp open hosts2-ns
82/tcp open xfer
83/tcp open mit-ml-dev

Si estas segur del que estas fent pots demanar a docker que elimini el servei que ja no està declarat amb l’opció --remove-orphans:

Terminal window
$ docker compose up -d --remove-orphans
Removing orphan container "cluster_apache_1"
cluster_apache_1_1 is up-to-date
cluster_apache_2_1 is up-to-date
cluster_apache_3_1 is up-to-date

Verifica que el contenidor cluster_apache_1 s’ha eliminat:

Terminal window
{% raw %}docker ps -a --format "table {{.ID}}\t{{.Names}}\t{{.Status}}" {% endraw %}
CONTAINER ID NAMES STATUS
8ae4c9a9b99e cluster_apache_1_1 Up 10 minutes
576213c0c870 cluster_apache_3_1 Up 10 minutes
a242c257b255 cluster_apache_2_1 Up 10 minutes

Al fitxer docker-compose.yml també pots definir volums:

services:
apache_1:
image: httpd:2.4
volumes:
- htdocs:/usr/local/apache2/htdocs
ports:
- 81:80
apache_2:
image: httpd:2.4
volumes:
- htdocs:/usr/local/apache2/htdocs
ports:
- 82:80
apache_3:
image: httpd:2.4
volumes:
- htdocs:/usr/local/apache2/htdocs
ports:
- 83:80
volumes:
htdocs:

Torna a arrencar els contenidors:

Terminal window
$ docker-compose up -d
Creating volume "cluster_htdocs" with default driver
Recreating cluster_apache_1_1 ... done
Recreating cluster_apache_3_1 ... done
Recreating cluster_apache_2_1 ... done

Com que el fitxer declara un volum htdocs, docker s’encarrega de crear aquest volum.

Fixa’t que al igual que ha fet amb la xarxa i els contenidors el prefix és cluster:

Terminal window
$ docker volume ls
DRIVER VOLUME NAME
local cluster_htdocs

També que s’han tornar a crear els contenidors httpd.

Modifica el contingut htdocs d’un dels contenidors.

Terminal window
docker exec cluster_apache_1_1 /bin/sh -c "echo 'hello' > htdocs/index.html"

A continuació verificar que tots el contenidors comparteixen el mateix volum:

Terminal window
$ curl localhost:81
hello
$ curl localhost:82
hello
$ curl localhost:83
hello

Com que el contingut de la carpeta htdocs està montant en un volum podem eliminar el contenidors sense perdre l’estat:

Terminal window
$ docker compose down
Stopping cluster_apache_1_1 ... done
Stopping cluster_apache_2_1 ... done
Stopping cluster_apache_3_1 ... done
Removing cluster_apache_1_1 ... done
Removing cluster_apache_2_1 ... done
Removing cluster_apache_3_1 ... done
Removing network cluster_default

Pots veure que es borra tot (incloent la xarxa) excepte el volum:

Terminal window
$ docker volume ls
DRIVER VOLUME NAME
local cluster_htdocs

Si tornem a desplegar la composició tot torna a funcionar:

Terminal window
$ docker compose up -d
...
$ curl localhost:81
hello

A continuació crearem un proxy pels tres servidors web.

Crea un fitxer haproxy.cfg:

frontend proxy
bind :80
default_backend webservers
backend webservers
server s1 apache_1:80 check
server s2 apache_2:80 check
server s3 apache_3:80 check

Modifica el fitxer docker-compose.yml:

services:
proxy:
image: haproxy:2.9
sysctls:
net.ipv4.ip_unprivileged_port_start: 0
volumes:
- ${PWD}/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
ports:
- 80:80
- 8404:8404
apache_1:
image: httpd:2.4
volumes:
- htdocs:/usr/local/apache2/htdocs
apache_2:
image: httpd:2.4
volumes:
- htdocs:/usr/local/apache2/htdocs
apache_3:
image: httpd:2.4
volumes:
- htdocs:/usr/local/apache2/htdocs
volumes:
htdocs:

Per muntar el fitxer fem servir un volum anònim.

Si vols saber perquè afegim systctls ves a https://hub.docker.com/_/haproxy/

Para i arrenca de nou els contenidors:

Terminal window
$ docker compose stop
...
$ docker compose up -d
...
Starting cluster_apache_2_1 ... done
Creating cluster_proxy_1 ... done

És molt important que el fitxer haproxy.cfg acabi amb un LFen la última linia.

Si no tindràs aquest error:

$ curl localhost
curl: (7) Failed to connect to localhost port 80 after 0 ms: S’ha refusat la connexió

I si mires el log del contenidor trobaràs aquesta explicació:

Terminal window
$ docker logs cluster_proxy_1
...
[ALERT] (1) : config : parsing [/usr/local/etc/haproxy/haproxy.cfg:8]: Missing LF on last line, file might have been truncated at position 30.
[ALERT] (1) : config : Error(s) found in configuration file : /usr/local/etc/haproxy/haproxy.cfg
[ALERT] (1) : config : Fatal errors found in configuration.

✅ Si no t’ha passat modifica el fitxer haproxy.cfg perquè doni aquest error. És important que aprenguis a solucionar aquestes situacions per tu mateix ja que ChatGPT no ho farà per tu.

Verifica que el proxy funciona:

Terminal window
$ curl localhost
TODO

A {% link “/linux/docker/network/” %} vam configurar un proxy de manera imperativa.

Ara tenim un fitxer docker-compose.yml que ens permet configurar un proxy de manera declarativa.

Elimina els contenidors:

Terminal window
$ docker compose stop
$ docker compose rm

A continuació tens conjunt d’aplicacions web que es composen de diversos components que s’han desplegat mitjançant Docker Compose.

Aquestes aplicacions s’utilitzen en diferents activitats formatives:

{% pages [“/web/app/etherpad/”, “/web/app/cryptpad/”, “/web/app/wordpress/”, “/web/app/odoo/”] %}


El contingut d'aquest lloc web té llicència CC BY-NC-ND 4.0.

©2022-2025 xtec.dev