© Copyright 2026 Ferrantino Francesco

Un container non è una macchina virtuale né un’entità separata dal sistema operativo. Dal punto di vista del kernel un container è costituito da uno o più processi Linux avviati sul sistema host isolati tramite namespace e limitati tramite cgroup ed eseguiti direttamente dal kernel.




Il kernel Linux vede i processi dei container allo stesso modo di qualsiasi altro processo. Nei paragrafi seguenti questo comportamento verrà mostrato con esempi pratici utilizzando Podman e Docker senza entrare ancora nei dettagli dei rispettivi strumenti.

I container sono molto leggeri perché non emulano un sistema operativo completo: condividono il kernel della macchina che li ospita e isolano solo i processi necessari. Questo li rende rapidi da avviare, spesso in pochi secondi e perfetti per microservizi o ambienti di sviluppo e test in cui serve creare e distruggere applicazioni velocemente. Queste caratteristiche possono essere riassunte in quattro punti chiave fondamentali:
  • isolamento: un container è un ambiente isolato dove eseguire un servizio o un'applicazione in autonomia. Non prevedono l'hypervisor come le VM ma l'esecuzione all'interno del kernel della macchina host attraverso il Docker Engine possiamo gestire ed eseguire i container.
  • overhead: significa “peso aggiuntivo” o “costo extra” in termini di risorse. Nei container l’overhead è minimo perché non devono avviare un intero sistema operativo.
  • avvio: secondi.
  • uso tipico: microservizi, workflow dev/test. Indica il modo in cui sviluppatori e tester lavorano ogni giorno. Con i container è facile creare, provare, modificare e distruggere ambienti di sviluppo e test in pochi secondi senza sporcare il sistema e senza configurazioni complicate.
Una macchina virtuale invece riproduce un intero sistema operativo con il proprio kernel, gestito da un hypervisor, e per questo ha un isolamento molto più forte ma anche un consumo di risorse decisamente maggiore. Di solito impiega decine di secondi o anche minuti per avviarsi e viene usata quando serve un ambiente completamente separato o quando l’isolamento deve essere totale. Queste caratteristiche possono essere riassunte in quattro punti chiave fondamentali:
  • isolamento: sistema operativo completo. Kernel della VM distinto da quello dell’host. L’hypervisor gestisce l’isolamento tra VM e host.
  • overhead: significa “peso aggiuntivo” o “costo extra” in termini di risorse. Nelle macchine virtuali è maggiore perché devono caricare kernel, servizi e tutto il sistema completo.
  • avvio: decine di secondi o minuti. Si riferisce al tempo necessario per far partire l’ambiente. Un container parte in pochi secondi perché non deve avviare un sistema operativo. Una macchina virtuale invece impiega molto più tempo, anche decine di secondi o minuti, proprio perché deve caricare un intero sistema operativo da zero.
  • uso tipico: isolamento completo.

Docker e Podman non introducono nuovi meccanismi di isolamento: si limitano a combinare e orchestrare funzionalità già presenti nel kernel Linux. Per questo motivo, comprendere processi, chroot, namespaces e cgroups significa comprendere le fondamenta di qualsiasi container runtime.

Gli esempi riportati possono essere eseguiti in modo equivalente sia con Podman sia con Docker poiché il comportamento osservato è determinato dal kernel Linux e non dal runtime utilizzato.


Docker


Se avviamo un container che contiene ad esempio NGINX i suoi processi saranno visibili tramite i normali strumenti di sistema come ps:
frank@debian:~$ ps -fC nginx
UID          PID    PPID  C STIME TTY          TIME CMD
Se non ci sono processi NGINX in esecuzione questo comando non restituisce alcuna riga: indica che nessun processo nginx è attivo sul sistema. Avviamo ora il container sull’host utilizzando Docker:
frank@debian:~$ docker run --name serverweb -d nginx
ebea1a17a31c6d1861b903c64d692004bb5b66b904e896903c4da29e9e76f018
Dal momento che un container è un processo Linux possiamo verificarne la presenza rieseguendo il comando sull’host:
frank@debian:~$ ps -fC nginx
UID          PID    PPID  C STIME TTY          TIME CMD
root        3035    3009  0 17:39 ?        00:00:00 nginx: master process nginx -
101         3082    3035  0 17:39 ?        00:00:00 nginx: worker process
101         3083    3035  0 17:39 ?        00:00:00 nginx: worker process

Sull’host è ora in esecuzione un’istanza del server web NGINX. Come per qualsiasi altro processo annotiamo il relativo PID 3035. Per verificare la presenza di container in esecuzione e distinguerli dai processi tradizionali possiamo utilizzare due modalità:

1 modalità
frank@debian:~$ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
ebea1a17a31c   nginx     "/docker-entrypoint.…"   23 minutes ago   Up 23 minutes   80/tcp    serverweb
2 modalità
frank@debian:~$ ps -ef --forest
UID          PID    PPID  C STIME TTY          TIME CMD
...
root        2479       1  0 17:23 ?        00:00:05 /usr/bin/containerd
root        2592       1  0 17:23 ?        00:00:02 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/
root        3009       1  0 17:39 ?        00:00:00 /usr/bin/containerd-shim-runc-v2 -namespace moby -id eb
root        3035    3009  0 17:39 ?        00:00:00  \_ nginx: master process nginx -g daemon off;
101         3082    3035  0 17:39 ?        00:00:00      \_ nginx: worker process
101         3083    3035  0 17:39 ?        00:00:00      \_ nginx: worker process
...

Con Docker esiste un demone centrale (dockerd): i processi del container appaiono comunque come normali processi Linux ma non sono figli diretti dell’utente e vengono avviati e mantenuti tramite dockerd, containerd e containerd-shim.

Il filesystem /proc contiene le informazioni su tutti i processi in esecuzione sull’host. Ogni directory numerica rappresenta un PID e fornisce una vista dettagliata dello stato del processo. È possibile ispezionare il filesystem visto dal container accedendo alla directory:
frank@debian:~$ sudo ls /proc/3035/root
[sudo] password for frank: 
bin   docker-entrypoint.d   home   media  proc  sbin  tmp
boot  docker-entrypoint.sh  lib    mnt    root  srv   usr
dev   etc                   lib64  opt    run   sys   var
È inoltre possibile modificare i file di un container accedendo direttamente al suo filesystem tramite l’host navigando in /proc/PID/root che espone la directory radice vista dal processo in esecuzione all’interno del container. Possiamo creare un nuovo file all’interno del container tramite Docker:
frank@debian:~$ docker exec serverweb touch /file01
  
frank@debian:~$ docker exec serverweb ls -l
total 64
lrwxrwxrwx   1 root root    7 Nov  7 17:40 bin -> usr/bin
drwxr-xr-x   2 root root 4096 Nov  7 17:40 boot
drwxr-xr-x   5 root root  340 Jan  3 16:39 dev
drwxr-xr-x   1 root root 4096 Dec 29 23:22 docker-entrypoint.d
-rwxr-xr-x   1 root root 1620 Dec 29 23:21 docker-entrypoint.sh
drwxr-xr-x   1 root root 4096 Jan  3 16:39 etc
-rw-r--r--   1 root root    0 Jan  3 17:47 file01
drwxr-xr-x   2 root root 4096 Nov  7 17:40 home
lrwxrwxrwx   1 root root    7 Nov  7 17:40 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Nov  7 17:40 lib64 -> usr/lib64
drwxr-xr-x   2 root root 4096 Dec 29 00:00 media
drwxr-xr-x   2 root root 4096 Dec 29 00:00 mnt
drwxr-xr-x   2 root root 4096 Dec 29 00:00 opt
dr-xr-xr-x 178 root root    0 Jan  3 16:39 proc
drwx------   2 root root 4096 Dec 29 00:00 root
drwxr-xr-x   1 root root 4096 Jan  3 16:39 run
lrwxrwxrwx   1 root root    8 Nov  7 17:40 sbin -> usr/sbin
drwxr-xr-x   2 root root 4096 Dec 29 00:00 srv
dr-xr-xr-x  13 root root    0 Jan  3 16:39 sys
drwxrwxrwt   2 root root 4096 Dec 29 00:00 tmp
drwxr-xr-x   1 root root 4096 Dec 29 00:00 usr
drwxr-xr-x   1 root root 4096 Dec 29 00:00 var
oppure
frank@debian:~$ sudo ls -l /proc/3035/root/
total 64
lrwxrwxrwx   1 root root    7 Nov  7 18:40 bin -> usr/bin
drwxr-xr-x   2 root root 4096 Nov  7 18:40 boot
drwxr-xr-x   5 root root  340 Jan  3 17:39 dev
drwxr-xr-x   1 root root 4096 Dec 30 00:22 docker-entrypoint.d
-rwxr-xr-x   1 root root 1620 Dec 30 00:21 docker-entrypoint.sh
drwxr-xr-x   1 root root 4096 Jan  3 17:39 etc
-rw-r--r--   1 root root    0 Jan  3 18:47 file01
drwxr-xr-x   2 root root 4096 Nov  7 18:40 home
lrwxrwxrwx   1 root root    7 Nov  7 18:40 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Nov  7 18:40 lib64 -> usr/lib64
drwxr-xr-x   2 root root 4096 Dec 29 01:00 media
drwxr-xr-x   2 root root 4096 Dec 29 01:00 mnt
drwxr-xr-x   2 root root 4096 Dec 29 01:00 opt
dr-xr-xr-x 178 root root    0 Jan  3 17:39 proc
drwx------   2 root root 4096 Dec 29 01:00 root
drwxr-xr-x   1 root root 4096 Jan  3 17:39 run
lrwxrwxrwx   1 root root    8 Nov  7 18:40 sbin -> usr/sbin
drwxr-xr-x   2 root root 4096 Dec 29 01:00 srv
dr-xr-xr-x  13 root root    0 Jan  3 18:47 sys
drwxrwxrwt   2 root root 4096 Dec 29 01:00 tmp
drwxr-xr-x   1 root root 4096 Dec 29 01:00 usr
drwxr-xr-x   1 root root 4096 Dec 29 01:00 var
Poiché un container è visto dal kernel come un normale processo Linux è possibile terminarlo utilizzando il comando kill sul suo PID causando l’arresto immediato del container.
frank@debian:~$ sudo kill 3035

frank@debian:~$ docker ps -a
CONTAINER ID   IMAGE         COMMAND                  CREATED             STATUS                      PORTS     NAMES
ebea1a17a31c   nginx         "/docker-entrypoint.…"   About an hour ago   Exited (0) 27 seconds ago             serverweb
Il container risulta fermo ma non viene eliminato: Docker continua infatti a mostrarlo tra i container esistenti nonostante STATUS Exited: Il processo non esiste più e quindi la directory /proc/PID non è più accessibile:
frank@debian:~$ cd /proc/3035
-bash: cd: /proc/3035: No such file or directory
Tentare di entrare nel container con docker exec fallisce perché il container non è in stato Running:
frank@debian:~$ docker exec serverweb ls /
Error response from daemon: container ebea1a17a31c6d1861b903c64d692004bb5b66b904e896903c4da29e9e76f018 is not running
Anche se il processo è terminato, il container continua a esistere come oggetto gestito da Docker. Per questo motivo il nome resta occupato e non può essere riutilizzato:
frank@debian:~$ docker run --name serverweb -d nginx
docker: Error response from daemon: Conflict. The container name "/serverweb" is already in use by container "ebea1a17a31c6d1861b903c64d692004bb5b66b904e896903c4da29e9e76f018". You have to remove (or rename) that container to be able to reuse that name.

Run 'docker run --help' for more information
Questo dimostra che:
  • un processo scompare quando termina
  • un container resta definito finché non viene rimosso esplicitamente
Per riutilizzare il nome del container è necessario rimuoverlo
frank@debian:~$ docker rm serverweb
Avviamo ora nuovamente il container sull’host utilizzando Docker:
frank@debian:~$ docker run --name serverweb -d nginx
7756e3022f69008867ab93684f4c87db97b600a02f05c84e52988cfbfc1273d8

Un container è semplicemente un processo Linux: chi ha accesso all’host può vederne i processi, analizzarne il comportamento e ispezionare informazioni come le variabili d’ambiente tramite /proc/PID/environ. Anche se questi strumenti non sono container-aware restano fondamentali per il debug, l’analisi delle performance e la sicurezza.

Poiché un container è visto dal kernel come un normale processo Linux la sua gestione avviene attraverso operazioni ben definite sul suo ciclo di vita. Docker fornisce comandi dedicati per arrestare, terminare o rimuovere un container, ognuno con un significato preciso.

Docker mette a disposizione diversi comandi per gestire il ciclo di vita di un container. Ogni comando ha uno scopo preciso ed è importante usarlo nel contesto corretto.

Stop pulito (consigliato): il comando docker stop invia un segnale di terminazione al processo principale del container permettendogli di chiudersi correttamente.
frank@debian:~$ docker stop serverweb
Stop forzato: il comando docker kill termina immediatamente il processo del container. È l’equivalente di un kill -9 e va usato solo in caso di necessità.
frank@debian:~$ docker kill serverweb
Rimozione del container: un container fermo continua a esistere come oggetto gestito da Docker. Per eliminarlo definitivamente è necessario utilizzare docker rm, operazione possibile solo dopo lo stop.
frank@debian:~$ docker rm serverweb

PODMAN


Se avviamo un container che contiene ad esempio NGINX i suoi processi saranno visibili tramite i normali strumenti di sistema come ps:
frank@fedora:~$ ps -fC nginx
UID          PID    PPID  C STIME TTY          TIME CMD
Se non ci sono processi NGINX in esecuzione questo comando non restituisce alcuna riga: indica che nessun processo nginx è attivo sul sistema. Avviamo ora il container sull’host utilizzando Podman:
frank@fedora:~$ podman run --name serverweb -d nginx
eae419c458a3fd713c9e3e29352db188c92391c88325cbcb2f3be9fd72c0f745
Dal momento che un container è un processo Linux possiamo verificarne la presenza rieseguendo il comando sull’host:
frank@fedora:~$ ps -fC nginx
UID          PID    PPID  C STIME TTY          TIME CMD
frank       3886    3884  0 11:51 ?        00:00:00 nginx: master process nginx -g daemon off;
524388      3914    3886  0 11:51 ?        00:00:00 nginx: worker process
524388      3915    3886  0 11:51 ?        00:00:00 nginx: worker process
524388      3916    3886  0 11:51 ?        00:00:00 nginx: worker process
524388      3917    3886  0 11:51 ?        00:00:00 nginx: worker process
524388      3918    3886  0 11:51 ?        00:00:00 nginx: worker process
524388      3919    3886  0 11:51 ?        00:00:00 nginx: worker process
524388      3920    3886  0 11:51 ?        00:00:00 nginx: worker process
524388      3921    3886  0 11:51 ?        00:00:00 nginx: worker process
524388      3922    3886  0 11:51 ?        00:00:00 nginx: worker process
524388      3923    3886  0 11:51 ?        00:00:00 nginx: worker process
524388      3924    3886  0 11:51 ?        00:00:00 nginx: worker process
524388      3925    3886  0 11:51 ?        00:00:00 nginx: worker process

Sull’host è ora in esecuzione un’istanza del server web NGINX. Come per qualsiasi altro processo annotiamo il relativo PID 3886. Per verificare la presenza di container in esecuzione e distinguerli dai processi tradizionali possiamo utilizzare due modalità:

1 modalità
frank@fedora:~$ podman ps
CONTAINER ID  IMAGE                           COMMAND               CREATED         STATUS         PORTS       NAMES
eae419c458a3  docker.io/library/nginx:latest  nginx -g daemon o...  3 minutes ago  Up 3 minutes  80/tcp      serverweb
2 modalità
frank@fedora:~$ ps -ef --forest
UID          PID    PPID  C STIME TTY          TIME CMD
...
frank       3886    3884  0 11:51 ?        00:00:00  \_ nginx: master process nginx -g daemon off;
524388      3914    3886  0 11:51 ?        00:00:00      \_ nginx: worker process
524388      3915    3886  0 11:51 ?        00:00:00      \_ nginx: worker process
524388      3916    3886  0 11:51 ?        00:00:00      \_ nginx: worker process
524388      3917    3886  0 11:51 ?        00:00:00      \_ nginx: worker process
524388      3918    3886  0 11:51 ?        00:00:00      \_ nginx: worker process
524388      3919    3886  0 11:51 ?        00:00:00      \_ nginx: worker process
524388      3920    3886  0 11:51 ?        00:00:00      \_ nginx: worker process
524388      3921    3886  0 11:51 ?        00:00:00      \_ nginx: worker process
524388      3922    3886  0 11:51 ?        00:00:00      \_ nginx: worker process
524388      3923    3886  0 11:51 ?        00:00:00      \_ nginx: worker process
524388      3924    3886  0 11:51 ?        00:00:00      \_ nginx: worker process
524388      3925    3886  0 11:51 ?        00:00:00      \_ nginx: worker process
...

Con Podman non esiste un demone centrale come in Docker: i processi del container appaiono come normali processi Linux, figli diretti dell’utente o del processo Podman che li ha avviati.

Il filesystem /proc contiene le informazioni su tutti i processi in esecuzione sull’host. Ogni directory numerica rappresenta un PID e fornisce una vista dettagliata dello stato del processo. È possibile ispezionare il filesystem visto dal container accedendo alla directory:
frank@fedora:~$ sudo ls /proc/3886/root
[sudo] password di frank:
bin  boot  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
È inoltre possibile modificare i file di un container accedendo direttamente al suo filesystem tramite l’host navigando in /proc/PID/root che espone la directory radice vista dal processo in esecuzione all’interno del container. Possiamo creare un nuovo file all’interno del container tramite Podman:
frank@fedora:~$ podman exec serverweb touch /file01

frank@fedora:~$ podman exec serverweb ls -l /
oppure
frank@fedora:~$ sudo ls -l /proc/3886/root/
Poiché un container è visto dal kernel come un normale processo Linux è possibile terminarlo utilizzando il comando kill sul suo PID causando l’arresto immediato del container.
frank@fedora:~$ sudo kill 3886

frank@fedora:~$ podman ps -a
CONTAINER ID  IMAGE                           COMMAND               CREATED         STATUS                     PORTS       NAMES
eae419c458a3  docker.io/library/nginx:latest  nginx -g daemon o...  11 minutes ago  Exited (0) 44 seconds ago  80/tcp      serverweb
Il container risulta fermo ma non viene eliminato: Podman continua infatti a mostrarlo tra i container esistenti nonostante STATUS Exited: Il processo non esiste più e quindi la directory /proc/PID non è più accessibile:
frank@fedora:~$ cd /proc/3886
-bash: cd: /proc/3886: File o directory non esistente
Tentare di entrare nel container con podman exec fallisce perché il container non è in stato Running:
frank@fedora:~$ podman exec serverweb ls /
Error: can only create exec sessions on running containers: container state improper
Anche se il processo è terminato, il container continua a esistere come oggetto gestito da Podman. Per questo motivo il nome resta occupato e non può essere riutilizzato:
frank@fedora:~$ podman run --name serverweb -d nginx
Error: creating container storage: the container name "serverweb" is already in use by eae419c458a3fd713c9e3e29352db188c92391c88325cbcb2f3be9fd72c0f745. You have to remove that container to be able to reuse that name: that name is already in use, or use --replace to instruct Podman to do so.
Questo dimostra che:
  • un processo scompare quando termina
  • un container resta definito finché non viene rimosso esplicitamente
Per riutilizzare il nome del container è necessario rimuoverlo
frank@fedora:~$ podman rm serverweb
oppure sovrascriverlo con l’opzione --replace:
frank@fedora:~$ podman run --replace --name serverweb -d nginx
Avviamo ora nuovamente il container sull’host utilizzando Podman:
frank@fedora:~$ podman run --name serverweb -d nginx
ff701de5c37316135b42d30e68c293470fa0e89791598a6198673b02ecd6b119

Un container è semplicemente un processo Linux, chi ha accesso all’host può vederne i processi, leggere variabili d’ambiente sensibili tramite /proc/PID/environ, e analizzarne il comportamento con i classici strumenti di sistema ed anche se questi strumenti non sono container-aware restano fondamentali per debug, analisi delle performance e sicurezza.

Poiché un container è visto dal kernel come un normale processo Linux la sua gestione avviene attraverso operazioni ben definite sul suo ciclo di vita. Podman fornisce comandi dedicati per arrestare, terminare o rimuovere un container, ognuno con un significato preciso.

Podman mette a disposizione diversi comandi per gestire il ciclo di vita di un container. Ogni comando ha uno scopo preciso ed è importante usarlo nel contesto corretto.

Stop pulito (consigliato): il comando podman stop invia un segnale di terminazione al processo principale del container permettendogli di chiudersi correttamente.
frank@fedora:~$ podman stop serverweb
Stop forzato: il comando podman kill termina immediatamente il processo del container. È l’equivalente di un kill -9 e va usato solo in caso di necessità.
frank@fedora:~$ podman kill serverweb
Rimozione del container: un container fermo continua a esistere come oggetto gestito da Podman. Per eliminarlo definitivamente è necessario utilizzare podman rm, operazione possibile solo dopo lo stop.
frank@fedora:~$ podman rm serverweb
Ferrantino Francesco

Ferrantino Francesco

Cookie Policy

Leggi  informativa Cookie Policy
Il "Sito" utilizza i Cookie per rendere i propri servizi semplici e efficienti per l’utenza che visiona le pagine di franksoft.it

Disclaimer

L'autore degli articoli non si assume nessuna responsabilità per eventuali danni ai vostri dispositivi. Tutto ciò che viene spiegato è puramente a scopo dimostrativo.
Il presente sito non costituisce testata giornalistica in quanto non ha carattere periodico ed è aggiornato secondo la mia disponibilità e la reperibilità dei materiali ivi contenuti. Pertanto, non può essere considerato in alcun modo un prodotto editoriale ai sensi della Legge n. 62 del 7/03/2001.

Licenza

Tutte le immagini presenti nel sito appartengono ai rispettivi titolari e sono utilizzate senza alcuno scopo di lucro. Ogni eventuale violazione del copyright non è intenzionale.
Quest'opera è distribuita con Licenza Creative Commons Attribuzione - Non commerciale - Non opere derivate 4.0 Internazionale.  Licenza Creative Commons