Gestern habe ich beschrieben, wie ein Docker Image mit Squid erstellt werden kann, basierend auf Alpine. Um das Ganze aber sinnvoll nutzen zu können, muss es möglich sein, den Container detached, also ohne interaktive Konsole zu starten. Danach sollte der Container dann aktiv bleiben, bis entweder ein Fehler auftritt, oder der Container von aussen gestoppt wird.

Das funktioniert mit dem bisherigen Image aber noch nicht, wie ich sehr einfach mit diesen beiden Kommandos auf der Shell demonstrieren kann:

podman run -d -p 3128:3128 71c1877c2525 /bin/sh
podman container ls -a
CONTAINER ID  IMAGE                                                             COMMAND  CREATED         STATUS                     PORTS  NAMES
b971bdbe3db3  71c1877c2525a974fc053fbf3a597433c5978d11f1a6eaa6d85762c1c485e079  /bin/sh  28 seconds ago  Exited (0) 28 seconds ago         trusting_hugle

Mit anderen Worten, der Container startet und beendet sich praktisch unmittelbar wieder. Mittels

podman logs -l

wird auch klar, dass es nicht etwas an einem Fehler liegt. Es liegt an einer Eigenschaft der Container Runtime, dass ein Container wieder beendet wird, sobald keine Programme mehr aktiv sind. Daemons oder andere Hintergrundprozesse sind dafür nicht genug. Wenn ich den Container interaktiv starte, funktioniert alles, das zweite Kommando habe ich einfach in einer zweiten Shell eingegeben.

podman run -it -p 3128:3128 71c1877c2525 /bin/sh
podman container ls -a
CONTAINER ID  IMAGE                                                             COMMAND  CREATED         STATUS                    PORTS                   NAMES
55222753d7e0  71c1877c2525a974fc053fbf3a597433c5978d11f1a6eaa6d85762c1c485e079  /bin/sh  49 seconds ago  Up 48 seconds ago         0.0.0.0:3128->3128/tcp  brave_ptolemy
b971bdbe3db3  71c1877c2525a974fc053fbf3a597433c5978d11f1a6eaa6d85762c1c485e079  /bin/sh  8 minutes ago   Exited (0) 8 minutes ago                          trusting_hugle

Was benötigt wird, ist in dem Dockerfile entweder eine ENTRYPOINT oder eine CMD Anweisung, die zwei Punkte erledigt:

  • squid starten, sobald der Container startet
  • einen Prozess im Vordergrund aktiv halten, der möglichst wenig Resourcen verbraucht.

Doch zurück zu meiner ersten Shell, woch ich jetzt ‘im’ Container bin. Dort starte ich einfach einmal squid:

/ # /usr/sbin/squid
/ # squid[3]: Squid Parent: will start 1 kids
squid[3]: Squid Parent: (squid-1) process 5 started

/ #

Auf meiner Workstation kann ich jetzt einfach versuchen mich mit Port 3128 zu verbinden:

Screenshot Squid

Die Fehlermeldung, die erscheint ist normal, da ich ja keine Webseite via des Proxy angefordert habe, aber die Tatsache, dass eine squid Fehlerseite erscheint, heißt, dass Squid läuft.

Man kann aus dem Terminal oben erkennen, dass das Kommando /usr/sbin/squid squid im Hintergrund startet. Auf einer normalen Linux Installation ist das ja auch exakt was man will, denn squid soll ja auch weiterlaufen, wenn man andere Aufgaben auf dem Terminal erledigen will. Für das Image ist das aber nicht genug, denn wenn ich als Entrypoint einfach /usr/sbin/squid angebe, wird der Container weiterhin direkt nach dem Start wieder beendet. Ich habe also derzeit ein lauffähiges Image, dass sich aber nicht als Anwendung startet lässt.

Bei Etutorials findet sich eine übersichtliche Doku der squid commandline,um es mir einfach zu machen, habe ich bei dem existierenden Image von Sameersbnabgeschaut. Es läuft daraufhinaus dass ein Script erstellt wird, dass als Entrypoint dient, mit diesem Inhalt.

#!/bin/sh
set -e

if [[ -z ${1} ]]; then
  if [[ ! -d ${SQUID_CACHE_DIR}/00 ]]; then
    echo "Initializing cache..."
    $(which squid) -N -f /etc/squid/squid.conf -z
  fi
  echo "Starting squid..."
  exec $(which squid) -f /etc/squid/squid.conf -NYCd 1 ${EXTRA_ARGS}
else
  exec "$@"
fi

Der wesentliche Trick um den Container aktiv zu halten, ist das exec. Dadurch bleibt die Shell weiterhin aktiv und hält damit auch den Container aktiv. Mittels dem Parameter -N startet squid als Vordergrundprozess. In dem Verzeichnis mit dem Dockerfile wird eine Datei entrypoint.sh erstellt mit dem obigen Inhalt, im Dockerfile wird die Datei dann mit ADD dem Image hinzugefügt und mittels ENTRYPOINT aktiviert. Das Dockerfile sind dann so aus:

ROM alpine

RUN apk add squid && \
    rm -rf /var/cache/apk/*

EXPOSE 3128/tcp

COPY entrypoint.sh /sbin/entrypoint.sh
RUN chmod 755 /sbin/entrypoint.sh

ENTRYPOINT ["/sbin/entrypoint.sh"]

Die beiden zusätzlichen Schritte erzeugen zwar weitere Layer im Image, die Größe des Images wird dadurch aber nicht wesentlich beinflusst.

Die Ergebnisse sind asls GitHub Repo und als DockerHub Image zu finden. Wer Probleme findet oder Vorschläge hat, kann sich gerne via GitHub beteiligen.