Docker y Colima en macOS🔗
Docker🔗
Debido a un cambio en la licencia de Docker Desktop puede uno considerar la búsqueda de alternativas para su uso en macOS.
Una alternativa es el uso de:
-
Docker CLI: principal herramienta en la linea de comandos para la administración de imágenes y contenedores.
-
Docker Compose: plugin para Docker CLI, permite la ejecución de aplicaciones en multi-contenedores definidos en un archivo
compose.yaml
(o biendocker-compose.yaml
) siguiendo The Compose Specification. -
Docker Buildx: plugin para Docker CLI, permite la construcción de imágenes definidos en un archivo
Containerfile
(o bienDockerfile
) siguiendo The Dockerfile reference. Internamente hace uso del proyecto Moby BuildKit. Cabe mencionar que Moby BuildKit permite el uso de otros lenguajes-referencias para la definición de una imagen.
Sobre la máquina virtual
Los contenedores, en este contexto, son una tecnología propia del kernel Linux (namespaces y cgroups) por lo que su uso y ejecución es transparente en una distribución de Linux. En el caso de macOS y Windows es necesario el uso de una maquina virtual con una distribución de Linux para poder hacer uso de contenedores.
Colima🔗
Colima permite la ejecución de un container runtime (Docker Engine/CE o containerd) dentro de una máquina virtual. Internamente hace uso de Lima para ejecutar/administrar una maquina virtual y en ella ejecutar un container runtime, incluyendo la autoconfiguración de port forwarding y volume mounts en esta.
Para crear e iniciar una instancia de colima (o una maquina virtual), y en ella al container runtime:
[nihilipster@localhost:~]$ colima start --runtime docker --arch aarch64 --cpu 8 --disk 120 --memory 32 --save-config --profile vm-aarch64-docker
INFO[0000] starting colima [profile=vm-aarch64-docker]
INFO[0000] runtime: docker
INFO[0001] creating and starting ... context=vm
INFO[0001] downloading disk image ... context=vm
INFO[0026] provisioning ... context=docker
INFO[0027] starting ... context=docker
INFO[0028] done
Sobre la instancia de colima
El nombre dado a la instancia de colima es mediante el argumento --profile
, mediante el cual se puede tener
distintos profiles con distintas características en cuanto a
arquitectura de CPU (--arch
),
numero de CPUs (--cpu
),
tamaño en GBs de Disco Duro (--disk
) y
tamaño en GBs de Memoria RAM (--memory
) disponibles a los contenedores que serán ejecutados en el container runtime.
Para listar la(s) instancia(s) de colima:
[nihilipster@localhost:~]$ colima list
PROFILE STATUS ARCH CPUS MEMORY DISK RUNTIME ADDRESS
vm-aarch64-docker Running aarch64 8 32GiB 120GiB docker
Para ver el status de la instancia de colima:
[nihilipster@localhost:~]$ colima --profile vm-aarch64-docker status
INFO[0000] colima [profile=vm-aarch64-docker] is running using macOS Virtualization.Framework
INFO[0000] arch: aarch64
INFO[0000] runtime: docker
INFO[0000] mountType: sshfs
INFO[0000] socket: unix://$HOME/.config/colima/vm-aarch64-docker/docker.sock
Configuración de la instancia de colima
La configuración de la instancia de colima se encuentra en $XDG_CONFIG_HOME/colima/<profile>/colima.yml
o
$HOME/.config/colima/<profile>/colima.yml
. En este caso sería $HOME/.config/colima/vm-aarch64-containerd/colima.yaml
.
Para detener y/o iniciar una instancia de colima previamente creada y/o configurada:
[nihilipster@localhost:~]$ colima --profile vm-aarch64-docker stop
INFO[0000] stopping colima [profile=vm-aarch64-docker]
INFO[0000] stopping ... context=docker
INFO[0000] stopping ... context=vm
INFO[0001] done
[nihilipster@localhost:~]$ colima --profile vm-aarch64-docker start
INFO[0000] starting colima [profile=vm-aarch64-docker]
INFO[0000] runtime: docker
INFO[0001] starting ... context=vm
INFO[0013] provisioning ... context=docker
INFO[0014] starting ... context=docker
INFO[0015] done
Para acceder por SSH a la instancia de colima:
[nihilipster@localhost:~]$ colima --profile vm-aarch64-docker ssh
nihilipster@colima-vm-aarch64-docker:$HOME$ cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.1 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo
nihilipster@colima-vm-aarch64-docker:$HOME$ exit
logout
Para ejecutar un comando por SSH dentro de la instancia de colima:
[nihilipster@localhost:~]$ colima --profile vm-aarch64-docker ssh -- cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.1 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo
Docker CLI🔗
Para la comunicación de Docker CLI con el container runtime es necesario la configuración de un Docker context, el cual contiene la información necesaria para la administración de los recursos ocupados por el container runtime.
Para listar los contextos configurados en Docker CLI:
[nihilipster@localhost:~]$ docker context list
NAME DESCRIPTION DOCKER ENDPOINT ERROR
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
El contexto por default de Docker y colima
Al momento de iniciar una instancia de colima se configurará a esta como un contexto en Docker CLI, siendo a su vez el contexto por default de Docker CLI, de tal manera que no es necesario hacer algo para que Docker CLI se comunique con el container runtime de la instancia de colima.
Si la instancia de colima se encuentra en ejecución se observará su presencia en la lista de contextos de Docker:
[nihilipster@localhost:~]$ docker context list
NAME DESCRIPTION DOCKER ENDPOINT ERROR
colima-vm-aarch64-docker * colima [profile=vm-aarch64-docker] unix://$HOME/.config/colima/vm-aarch64-docker/docker.sock
default Current DOCKER_HOST based configuration unix:///var/run/docker.sock
Sobre la variable de entorno $DOCKER_HOST
Otra manera de indicarle a Docker CLI la “instancia de Docker” a la cual conectarse es mediante la
variable de entorno DOCKER_HOST, siendo
en este caso:
DOCKER_HOST="unix://$HOME/.config/colima/vm-aarch64-docker/docker.sock"
.
Para obtener información sobre la comunicación entre el “cliente” (Docker CLI) y el “servidor” (container runtime):
[nihilipster@localhost:~]$ docker info
Client:
Version: 27.5.1
Context: colima-vm-aarch64-docker
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: 0.19.3
Path: /opt/local/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: 2.32.1
Path: /opt/local/libexec/docker/cli-plugins/docker-compose
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 27.4.0
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 88bf19b2105c8b17560993bee28a01ddc2f97182
runc version: v1.2.2-0-g7cb3632
init version: de40ad0
Security Options:
apparmor
seccomp
Profile: builtin
cgroupns
Kernel Version: 6.8.0-50-generic
Operating System: Ubuntu 24.04.1 LTS
OSType: linux
Architecture: aarch64
CPUs: 8
Total Memory: 31.28GiB
Name: colima-vm-aarch64-docker
ID: ade88927-1797-47c2-b328-c38c8c56b4ba
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
Imágenes y contenedores🔗
Para obtener una imagen desde algun container registry, por ejemplo la imagen oficial ‘hello-world’ en el Docker Hub:
[nihilipster@localhost:~]$ docker image pull hello-world:latest
Using default tag: latest
latest: Pulling from library/hello-world
c9c5fd25a1bd: Pull complete
Digest: sha256:d715f14f9eca81473d9112df50457893aa4d099adeb4729f679006bf5ea12407
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest
Para listar las imagenes locales:
[nihilipster@localhost:~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest f1f77a0f96b7 3 weeks ago 5.2kB
Para la ejecución de un contenedor, lo cual implica el uso de una imagen para la creación de dicho contenedor:
[nihilipster@localhost:~]$ docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(arm64v8)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
Para listar los contenedores creados localmente:
[nihilipster@localhost:~]$ docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b2fe5fa59b77 hello-world "/hello" 5 days ago Exited (0) 5 days ago interesting_burnell
Para crear un contenedor, en base a una imagen ya existente localmente, y ejecutarlo:
[nihilipster@localhost:~]$ docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b2fe5fa59b77 hello-world "/hello" 5 days ago Exited (0) 5 days ago interesting_burnell
[nihilipster@localhost:~]$ docker container create --name hola-mundo --tty --interactive hello-world:latest
845edb0399be0711e4011c212e35881f96e26873657df426cbdf17b9a1d8afc7
[nihilipster@localhost:~]$ docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
845edb0399be hello-world:latest "/hello" 4 seconds ago Created hola-mundo
b2fe5fa59b77 hello-world "/hello" 5 days ago Exited (0) 5 days ago interesting_burnell
[nihilipster@localhost:~]$ docker container start --attach --interactive hola-mundo
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(arm64v8)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
Docker Buildx🔗
Docker Buildx extiende las características de docker build, haciendo uso del
proyecto Moby BuildKit, mediante el comando docker buildx
.
docker build vs docker buildx
A partir de la versión 23.0 de Docker Desktop, Moby BuildKit es quien realmente es ejecutado con el comando
docker build
por lo que de estar haciendo uso de Docker Desktop >= 23.0 ya no sería necesario activar el uso
de Moby BuildKit (mediante la variable de entorno DOCKER_BUILDKIT=1
). Cabe mencionar que ademas los comandos
docker build
y docker buildx build
tendrían el mismo comportamiento.
A manera de ejemplo se puede obtener la definición de la imagen de un contenedor de Postgres ubicada en el archivo https://github.com/docker-library/postgres/blob/master/17/bookworm/Dockerfile, el cual establece la configuración del sistema operativo Debian Bookworm, la instalación de paquetes necesarios para Postgres y el inicio de una instancia de Postgres.
Se obtiene el repositorio https://github.com/docker-library/postgres de manera local:
[nihilipster@localhost:~]$ git clone https://github.com/docker-library/postgres
Cloning into 'postgres'...
remote: Enumerating objects: 6949, done.
remote: Counting objects: 100% (152/152), done.
remote: Compressing objects: 100% (76/76), done.
remote: Total 6949 (delta 91), reused 96 (delta 76), pack-reused 6797 (from 4)
Receiving objects: 100% (6949/6949), 1.05 MiB | 3.03 MiB/s, done.
Resolving deltas: 100% (3067/3067), done.
Es posible analizar el contenido de la carpeta que contiene la definición de la imagen (postgres/17/bookworm/Dockerfile
):
[nihilipster@localhost:~]$ ls postgres/17/bookworm
Dockerfile docker-ensure-initdb.sh docker-entrypoint.sh
Para construir la imagen en base a la definición:
[nihilipster@localhost:~/postgres/17/bookworm]$ docker buildx build --tag postgres-17.2-debian-bookworm:17.2 --file postgres/17/bookworm/Dockerfile postgres/17/bookworm/
[+] Building 49.7s (19/19) FINISHED docker:colima-vm-aarch64-docker
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 9.86kB 0.0s
=> [internal] load metadata for docker.io/library/debian:bookworm-slim 1.2s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [ 1/14] FROM docker.io/library/debian:bookworm-slim@sha256:40b107342c492725bc7aacbe93a49945445191ae364184a6d24fedb28172f6f7 2.1s
=> => resolve docker.io/library/debian:bookworm-slim@sha256:40b107342c492725bc7aacbe93a49945445191ae364184a6d24fedb28172f6f7 0.0s
=> => sha256:40b107342c492725bc7aacbe93a49945445191ae364184a6d24fedb28172f6f7 8.56kB / 8.56kB 0.0s
=> => sha256:435e86e9f078a90c245ec35c494c44b4e9e8f53d0f8462ec3ad99f0ec6054f3d 1.04kB / 1.04kB 0.0s
=> => sha256:c0ab4e530f590d58f74eae4612d0baaf70ac2981b05eeb03c0786ae7b02288ab 468B / 468B 0.0s
=> => sha256:4d2547c084994a809c138e688fbe4ee14eedbc6e2defc5b1c680edd16e291473 28.04MB / 28.04MB 1.3s
=> => extracting sha256:4d2547c084994a809c138e688fbe4ee14eedbc6e2defc5b1c680edd16e291473 0.8s
=> [internal] load build context 0.0s
=> => transferring context: 15.13kB 0.0s
=> [ 2/14] RUN set -eux; groupadd -r postgres --gid=999; useradd -r -g postgres --uid=999 --home-dir=/var/lib/postgresql --shell=/bin/bash 0.2s
=> [ 3/14] RUN set -ex; apt-get update; apt-get install -y --no-install-recommends gnupg less ; rm -rf /var/lib/apt/lists/* 4.1s
=> [ 4/14] RUN set -eux; savedAptMark="$(apt-mark showmanual)"; apt-get update; apt-get install -y --no-install-recommends ca-certificates 8.0s
=> [ 5/14] RUN set -eux; if [ -f /etc/dpkg/dpkg.cfg.d/docker ]; then grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; sed -ri '/ 4.1s
=> [ 6/14] RUN set -eux; apt-get update; apt-get install -y --no-install-recommends libnss-wrapper xz-utils zstd ; rm -rf /var/lib/ 3.3s
=> [ 7/14] RUN mkdir /docker-entrypoint-initdb.d 0.1s
=> [ 8/14] RUN set -ex; key='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8'; export GNUPGHOME="$(mktemp -d)"; mkdir -p /usr/local/share/keyring 0.6s
=> [ 9/14] RUN set -ex; export PYTHONDONTWRITEBYTECODE=1; dpkgArch="$(dpkg --print-architecture)"; aptRepo="[ signed-by=/usr/local/shar 25.0s
=> [10/14] RUN set -eux; dpkg-divert --add --rename --divert "/usr/share/postgresql/postgresql.conf.sample.dpkg" "/usr/share/postgresql/17/p 0.1s
=> [11/14] RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 0.1s
=> [12/14] RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "/var/lib/postgresql/data" 0.1s
=> [13/14] COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 0.0s
=> [14/14] RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 0.1s
=> exporting to image 0.5s
=> => exporting layers 0.5s
=> => writing image sha256:1aee1b100a039cb7863d564d5fe0b1804a55b2bbaa3bc19525b4c85aaad81faf 0.0s
=> => naming to docker.io/library/postgres-17.2-debian-bookworm:17.2
Para listar la nueva imagen creada:
[nihilipster@localhost:~]$ docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
postgres-17.2-debian-bookworm 17.2 1aee1b100a03 25 minutes ago 458MB
Una vez creada la imagen se pueden crear tanto contenedores se quieran.
Para borrar la imagen:
[nihilipster@localhost:~]$ docker image rm postgres-17.2-debian-bookworm:17.2
Untagged: postgres-17.2-debian-bookworm:17.2
Deleted: sha256:1aee1b100a039cb7863d564d5fe0b1804a55b2bbaa3bc19525b4c85aaad81faf
Docker Compose🔗
A manera de ejemplo se crearán los servicios de Postgres (como sistema gestor de base de datos) y pgAdmin (como aplicación web).
Para obtener la definición de los servicios desde el repositorio https://github.com/docker/awesome-compose:
[nihilipster@localhost:~]$ git clone https://github.com/docker/awesome-compose
Cloning into 'awesome-compose'...
remote: Enumerating objects: 2757, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 2757 (delta 0), reused 0 (delta 0), pack-reused 2753 (from 2)
Receiving objects: 100% (2757/2757), 7.70 MiB | 10.12 MiB/s, done.
Resolving deltas: 100% (1329/1329), done.
Creando los servicios mediante docker compose
:
[nihilipster@localhost:~]$ docker compose --env-file awesome-compose/postgresql-pgadmin/.env --file awesome-compose/postgresql-pgadmin/compose.yaml up
[+] Running 32/32
✔ pgadmin Pulled 11.1s
...
✔ postgres Pulled 15.5s
...
[+] Running 3/3
✔ Network postgresql-pgadmin_default Created 0.1s
✔ Container pgadmin Created 0.5s
✔ Container postgres Created 0.5s
Attaching to pgadmin, postgres
...
pgadmin | pgAdmin 4 - Application Initialisation
pgadmin | ======================================
pgadmin |
pgadmin | postfix/postlog: starting the Postfix mail system
pgadmin | [2025-02-13 05:50:48 +0000] [1] [INFO] Starting gunicorn 22.0.0
pgadmin | [2025-02-13 05:50:48 +0000] [1] [INFO] Listening at: http://[::]:80 (1)
pgadmin | [2025-02-13 05:50:48 +0000] [1] [INFO] Using worker: gthread
pgadmin | [2025-02-13 05:50:48 +0000] [118] [INFO] Booting worker with pid: 118
...
Gracefully stopping... (press Ctrl+C again to force)
[+] Stopping 2/2
✔ Container pgadmin Stopped 0.5s
✔ Container postgres Stopped 0.1s˜˜˜˜
Accediento a pgAdmin disponible en
El ususuario y la contraseña fueron definidos por las variables de entorno PGADMIN_MAIL=your@email.com
y PGADMIN_PW=changeit
en el archivo
awesome-compose/postgresql-pgadmin/.env
.
Sobre el parametro --env-file
Mediante --env-file
podemos indicar las variables de entorno disponibles a los servicios. En este caso el archivo awesome-compose/postgresql-pgadmin/.env
establece variables para la creación de la base de datos en Postgres y la autenticación en pgAdmin.
Tambien es posible conectar algún otro cliente de Postgres, en este caso DBeaver, teniendo en cuenta las variables de entorno
POSTGRES_USER=yourUser
, POSTGRES_PW=changeit
y POSTGRES_DB=postgres
definidas en el archivo awesome-compose/postgresql-pgadmin/.env
.