Diese Anleitung dokumentiert eine reale Ubuntu-24.04.4-LTS-Installation: Docker Engine aus dem offiziellen Repository, Compose- und Buildx-Prüfung, hello-world-Container-Test, Portainer CE LTS mit persistentem Volume, Nginx Reverse Proxy und Let's Encrypt für portainer.ekasunucu.com, einen realen Certbot-Snap-Timeout sowie die finale Bindung von Port 9443 ausschließlich an 127.0.0.1.
Ubuntu 24.04.4 LTS
↓ Docker Engine + Compose
Docker socket /var/run/docker.sock
↓
Portainer CE LTS :9443
↓ nur localhost
Nginx :443 + Let's Encrypt
↓
portainer.ekasunucu.comDiese Anleitung dokumentiert eine reale Installation auf einem Ubuntu-24.04.4-LTS-VPS. In der Testumgebung liefen Docker Engine 29.7.2, Docker Compose v5.4.0 und Portainer Community Edition 2.39.5 LTS; diese Versionsnummern beschreiben den Test und sind keine dauerhafte Mindestanforderung.
Ziel war nicht nur eine erreichbare Portainer-Oberfläche. Docker wurde aus dem offiziellen Repository installiert, Portainer-Daten liegen in einem Named Volume, Nginx arbeitet als Reverse Proxy, Let's Encrypt liefert TLS und Port 9443 wurde final ausschließlich an 127.0.0.1 gebunden.
Internet :443
↓
Nginx + Let's Encrypt
↓
https://127.0.0.1:9443
↓
Portainer CE LTS
↓
/var/run/docker.sock → Docker EngineVor der Installation sollten Ubuntu-Version, Kernel, Architektur, RAM und Speicherplatz dokumentiert werden. Der Test-VPS lief mit Ubuntu 24.04.4 LTS Noble, Kernel 6.8.0-137-generic und x86-64.
Vor der Nutzung offizieller Docker-Pakete vorhandene Pakete wie docker.io, docker-compose, containerd, runc oder podman-docker prüfen. Auf Produktivsystemen keine Pakete ohne Prüfung laufender Workloads entfernen.
cat /etc/os-release | grep -E 'PRETTY_NAME|VERSION_ID|VERSION_CODENAME'
uname -r
dpkg --print-architecturefree -h
df -h /dpkg --get-selections | grep -E 'docker|containerd|runc|podman' || trueDocker Engine wurde aus dem offiziellen Ubuntu-Repository von Docker installiert. ca-certificates und curl wurden vorbereitet, der Signaturschlüssel unter /etc/apt/keyrings/docker.asc gespeichert und docker.sources im deb822-Format erstellt.
Ein docker-ce-Kandidat aus Noble stable in apt-cache policy bestätigt die Repository-Verbindung. Im Test war Docker CE 29.7.2 der Kandidat.
apt-get update
apt-get install -y ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asccat >/etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
apt-get update
apt-cache policy docker-ceNach der Repository-Prüfung wurden docker-ce, docker-ce-cli, containerd.io, docker-buildx-plugin und docker-compose-plugin installiert. Im Test wurden 102 MB geladen; dieser Wert ist versionsabhängig.
Der Docker-Dienst wurde über systemd aktiviert und gestartet. Danach wurden Docker-, Compose- und Buildx-Versionen separat geprüft.
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginsystemctl enable --now docker
systemctl is-active dockerdocker --version
docker compose version
docker buildx versionDas erste Automatisierungsskript stoppte trotz funktionierendem Docker-Repository bei head -n 20 mit Exit Code 141. head schloss die Pipe früh, der vorherige Prozess erhielt SIGPIPE und set -o pipefail wertete dies als Fehler.
Für reine Anzeige-Pipelines kann sed -n genutzt werden. || true sollte nur bei eindeutig harmlosen Anzeigeoperationen eingesetzt werden; echte Installationsfehler dürfen nicht verborgen werden.
apt-cache policy docker-ce | sed -n '1,20p'apt-cache policy docker-ce | head -n 20 || truedocker --version bestätigt nur den Client. Deshalb wurde hello-world heruntergeladen und als Container ausgeführt. 'Hello from Docker!' bestätigte Client, Daemon, Image-Pull und Container-Ausführung gemeinsam.
Mit docker info wurden Storage Driver, Cgroup-Modus, Sicherheitsoptionen, Docker Root Dir und Ressourcen kontrolliert. Der Test zeigte overlayfs, cgroup v2, AppArmor und seccomp.
docker run --rm hello-worlddocker infosystemctl --failedFür dauerhafte Portainer-Konfiguration wurde das Named Volume portainer_data erstellt. Danach wurde portainer/portainer-ce:lts geladen und der lokale Docker-Socket in den Container eingebunden.
Für die erste reale Prüfung war 9443 kurz auf dem Host veröffentlicht. Nach Einrichtung von Nginx und Domain wurde Portainer final nur mit 127.0.0.1:9443 neu erstellt.
docker volume create portainer_data
docker pull portainer/portainer-ce:ltsdocker run -d --name portainer --restart=always -p 9443:9443 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:ltsdocker ps --filter name='^/portainer$'
curl -k -sS -o /dev/null -w '%{http_code}\n' https://127.0.0.1:9443/Eine frische Portainer-Datenbank zeigt beim ersten Start die Einrichtung des Administratorkontos. Im Test erzeugten die Logs zusätzlich ein temporäres Setup-Token. Dieses Token wie Passwort oder API-Key behandeln und niemals veröffentlichen.
Nach dem Admin-Setup erkennt der Environment Wizard die lokale Docker-Umgebung. Läuft die initiale Einrichtung wegen Inaktivität ab, kann der Container neu gestartet werden.
docker logs portainer --tail 100docker restart portainerFür portainer.ekasunucu.com wurden Nginx und dnsutils installiert. Erst nachdem Cloudflare DNS und Google DNS auf den erwarteten Origin zeigten, wurde der Reverse Proxy aktiviert.
Nginx leitet zu https://127.0.0.1:9443 weiter. Da Portainer lokal ein selbstsigniertes Zertifikat nutzt, wird proxy_ssl_verify off nur für diesen localhost-Upstream verwendet; öffentliches TLS terminiert Nginx mit Let's Encrypt.
apt-get update
apt-get install -y nginx dnsutils
systemctl enable --now nginxdig +short A portainer.ekasunucu.com @1.1.1.1
dig +short A portainer.ekasunucu.com @8.8.8.8cat >/etc/nginx/conf.d/portainer-websocket.conf <<'EOF'
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
EOFcat >/etc/nginx/sites-available/portainer.ekasunucu.com <<'EOF'
server {
listen 80;
listen [::]:80;
server_name portainer.ekasunucu.com;
location / {
proxy_pass https://127.0.0.1:9443;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_ssl_verify off;
}
}
EOF
ln -sfn /etc/nginx/sites-available/portainer.ekasunucu.com /etc/nginx/sites-enabled/portainer.ekasunucu.com
nginx -t
systemctl reload nginxcurl -sS -o /dev/null -w '%{http_code}\n' -H 'Host: portainer.ekasunucu.com' http://127.0.0.1/Der erste snap-install-Versuch für Certbot lief beim Download von core24 über Canonicals CDN in einen TCP-443-Timeout. Nginx und Portainer waren dabei weiterhin funktionsfähig; die Ursache lag im Snap-Downloadpfad.
snap changes und snapd-Status bestätigten dies. Ein späterer Versuch installierte Certbot 5.7.0 erfolgreich. Bei temporären CDN-/Netzwerkfehlern nicht vorschnell die Reverse-Proxy-Konfiguration ändern.
snap changes
systemctl is-active snapdsnap install --classic certbotsnap list certbot
/snap/bin/certbot --versionWährend der Fehlersuche wurden kurzzeitig auch Ubuntu-APT-Pakete von Certbot getestet. Final wurden certbot, python3-certbot und python3-certbot-nginx aus APT entfernt und ausschließlich Certbot 5.7.0 als Snap genutzt.
Eine einzige Binary und ein Renewal-Mechanismus vereinfachen Diagnose und Wartung. Auf bestehenden Produktivsystemen vorher Zertifikats- und Renewal-Konfiguration prüfen.
apt-get remove -y certbot python3-certbot python3-certbot-nginx python3-certbot || truesnap install --classic certbot
ln -sfn /snap/bin/certbot /usr/local/bin/certbot
certbot --versionNachdem der HTTP-Reverse-Proxy 200 lieferte, wurde das Let's-Encrypt-Zertifikat ausgestellt. Certbot speicherte es unter /etc/letsencrypt/live/portainer.ekasunucu.com und konfigurierte Nginx für HTTPS.
Nach der Ausstellung wurden nginx -t, HTTPS-Antwort sowie Subject, Issuer und Gültigkeitsdaten mit openssl geprüft.
certbot --nginx -d portainer.ekasunucu.com -m [email protected] --agree-tos --no-eff-email --redirectnginx -t
systemctl is-active nginxcurl -I https://portainer.ekasunucu.com/openssl s_client -connect portainer.ekasunucu.com:443 -servername portainer.ekasunucu.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -datesNach erfolgreichem Domain-/TLS-Pfad wurde Portainer mit demselben portainer_data-Volume neu erstellt und die Host-Zuordnung auf 127.0.0.1:9443:9443 geändert. Der Verwaltungsport lauscht damit nicht mehr auf öffentlichen Interfaces.
Das Named Volume erhält die Portainer-Datenbank beim Container-Neustart. Final sollte 9443 nur auf Loopback und 80/443 über Nginx sichtbar sein.
docker stop portainer
docker rm portainerdocker run -d --name portainer --restart=always -p 127.0.0.1:9443:9443 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:ltsdocker ps --filter name='^/portainer$'
ss -lntp | grep -E ':(80|443|9443)\b'curl -k -sS -o /dev/null -w '%{http_code}\n' https://127.0.0.1:9443/
curl -sS -o /dev/null -w '%{http_code}\n' https://portainer.ekasunucu.com/Ein heute gültiges Zertifikat braucht einen überprüften Erneuerungsweg. Daher wurde der snap.certbot.renew-Timer kontrolliert und certbot renew --dry-run ausgeführt.
Die simulierte Erneuerung war erfolgreich. Zusammen mit nginx -t ist dies ein wichtiger Test vor dem unbeaufsichtigten Betrieb.
systemctl list-timers --all | grep -i certbot || truecertbot renew --dry-runnginx -tDie finale Portainer-Anmeldung erfolgte nur über https://portainer.ekasunucu.com. Nach dem Login erkannte der Environment Wizard den lokalen Docker-Socket und bot die lokale Umgebung an.
Auf der Startseite erschien local als Up; Container, Volume, Images sowie CPU/RAM wurden angezeigt. Damit war auch die tatsächliche Docker-Verwaltung über Portainer bestätigt.
https://portainer.ekasunucu.comZum Abschluss Docker- und Nginx-Dienste, Portainer-Container, Named Volume, Docker-Speicher, HTTPS-Status und fehlgeschlagene systemd-Units getrennt prüfen. Der Test endete mit HTTP 200 und null failed units.
Diese Prüfungen nach einem Reboot wiederholen. Docker-Restart-Policy, Nginx-Autostart, Portainer und Domain-TLS dürfen nicht von einer interaktiven SSH-Sitzung abhängen.
systemctl is-active docker nginx
docker ps
docker volume lsdocker system dfcurl -sS -o /dev/null -w 'HTTPS %{http_code}\n' https://portainer.ekasunucu.com/ss -lntp | grep -E ':(80|443|9443)\b'
systemctl --failedJa. Diese Anleitung dokumentiert Docker Engine 29.7.2 auf Ubuntu 24.04.4 LTS Noble. Für neue Installationen die aktuell unterstützten Versionen der offiziellen Docker-Dokumentation verwenden.
Damit Docker CE, Compose und Buildx aus dem Ubuntu-Paketkanal von Docker mit zusammenpassenden Plugins installiert werden.
docker --version prüft nur den Client. hello-world testet Daemon-Verbindung, Image-Pull, Container-Erstellung und Ausgabe gemeinsam.
Portainer stellt HTTPS auf 9443 bereit. Final lauscht der Host hier nur auf 127.0.0.1:9443; öffentlich wird Portainer über Nginx auf 443 erreicht.
In dieser Architektur wird es nur für den lokalen Upstream verwendet. Öffentliches TLS wird durch Nginx mit Let's Encrypt bereitgestellt.
Nicht wenn das Named Volume portainer_data erhalten bleibt. Das Volume beim Container-Austausch nicht löschen.
Ein sensibles temporäres Token für die erste Administration einer frischen Installation. Wie ein Passwort behandeln und nicht veröffentlichen.
snap changes, snapd und ausgehendes HTTPS prüfen. Im Test lief ein Canonical-CDN-Download in einen Timeout; ein späterer Versuch war erfolgreich.
Nicht in der finalen Konfiguration dieser Anleitung. APT-Certbot-Pakete wurden entfernt und Snap Certbot verwendet.
Nginx bietet bereits sicheren Domainzugriff auf 443. Der rohe Portainer-Verwaltungsport muss deshalb nicht zusätzlich auf der öffentlichen IP lauschen.
certbot renew --dry-run simuliert die Erneuerung ohne das aktive Zertifikat zu ersetzen. Unser Test war erfolgreich.
Wenn /var/run/docker.sock in Portainer eingebunden ist, kann der Environment Wizard den lokalen Docker-Host erkennen und über Get Started anbieten.
In dieser Architektur lauscht Nginx öffentlich auf 80/443; Portainer 9443 bleibt nur auf Loopback. SSH und weitere Dienste separat absichern.
Auf einem geeigneten Ubuntu-VPS mit Root/SSH, genügend RAM/SSD und passender Sicherheitsrichtlinie kann dieselbe Architektur eingesetzt werden. Der Ressourcenbedarf hängt von den Containern ab.
Docker Engine, Portainer, Nginx, Ollama, Open WebUI, n8n und weitere Self-Hosted-Dienste auf eigener Infrastruktur mit EKA Server Linux VPS betreiben.
Aktualisiert: 10.08.2026