Will man mal schnell einen separaten Docker Host erstellen, so geht das in Proxmox recht schnell. Hier gibt es die Virtualisierung „LXC“ – die Linux Container Runtime. Hier kann basierend auf dem Host-Betriebssystem (Proxmox 8.2.8 in meinem Fall) eine VM erstellt werden. Sieht aus, wie eine echte VM, ist es aber nicht. Das LXC Betriebssystem basiert vollständig auf dem Host-Betriebssystem.
Mit einem solchen Container kann man in wenigen Schritten Docker installieren. Im folgenden habe ich zusammengeschrieben, welche Schritte dafür notwendig sind – quasi „quick and dirty“.
LXC VM erstellen
Webinterface – Rechts oben „Create CT“
Hostname definieren (docker01)
„Unprivileged container“ deaktivieren
Passwort zwei mal eintippen.
Next
Storage wählen und darauf das
Debian Image auswählen (12-standard_12.7-1_amd64.tar.zst) stand heute.
Strage „rootfs“ Größe definieren (30G)
Zweiten Storage erstellen (mp0) – path /mnt/containers
Disk size 1000 GB
Next
4 Cores
Next
Memory 16000 und swap 2000
Next
Network – IPv4 – DHCP anwählen oder statische IP vergeben – je nach Bedarf
Next
Next
„Finish“
VM – Options – Doppelklick „Features“ – aktivieren:
– Nesting
– NFS
– SMB/CIFS
OK
VM starten
VM – Installation mit Docker und Portainer
Login in die Console mit root und dem angelegten Passwort
ip addr
Zeigt die IP an, die das System hat. Danach permit root login und Updates
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config
apt autoclean -y && apt autoremove --purge -y && apt update && apt upgrade -y && apt dist-upgrade -y && reboot now
Jetzt per kitty anmelden und Docker installieren.
Offizielle Doku: https://docs.docker.com/engine/install/debian/
Das ganze aber ohne sudo ausführen:
# Add Docker's official GPG key:
apt-get update
apt-get install ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
Installieren:
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin htop -y
Spaßeshalber die Installation testen:
docker run hello-world
Danach Portainer installieren und starten
docker run -d -p 9000:9000 -p 9443:9443 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v /mnt/containers/portainer/data:/data portainer/portainer-ce
Danach per Webinterface Portainer aufrufen und entweder das Backup wiederherstellen oder Portainer einrichten.
Docker Container
Einige Docker Container sind für mich für jede Installation unerlässlich. Deswegen kurz und bündig einige meiner Favoriten, auf die ich gerne zurückgreife.
Nice-to-have: Portainer Registry
version: "3.2"
services:
docker-registry:
image: registry:2
restart: unless-stopped
ports:
- 5000:5000
volumes:
- /mnt/containers/docker-registry/data/:/var/lib/registry/
- /mnt/containers/docker-registry/config/config.yml:/etc/docker/registry/config.yml
environment:
- REGISTRY_STORAGE_DELETE_ENABLED=TRUE
Dazu die config.yml
version: 0.1
log:
fields:
service: registry
storage:
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
delete:
enabled: true
# tag:
# concurrencylimit: 8
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3
proxy:
remoteurl: https://registry-1.docker.io
Das wird alles hinter den HAProxy gehängt oder hinter einen traefik.
Url: registry.xxxx.example.org
Must-have: Watchtower für automatische Updates von Container
version: "3"
services:
watchtower:
restart: unless-stopped
image: containrrr/watchtower:latest
tty: true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_DEBUG=true
#- WATCHTOWER_LABEL_ENABLE=true
- WATCHTOWER_INCLUDE_RESTARTING=true
# Entry | Description | Equivalent To
# ----- | ----------- | -------------
# @yearly (or @annually) | Run once a year, midnight, Jan. 1st | 0 0 0 1 1 *
# @monthly | Run once a month, midnight, first of month | 0 0 0 1 * *
# @weekly | Run once a week, midnight between Sat/Sun | 0 0 0 * * 0
# @daily (or @midnight) | Run once a day, midnight | 0 0 0 * * *
# @hourly | Run once an hour, beginning of hour | 0 0 * * * *
# I want watchtower to check for new updates every night at 4am.
#- WATCHTOWER_SCHEDULE: 0 0 4 * * *
#- WATCHTOWER_SCHEDULE=0 0 5 1 * *
- WATCHTOWER_SCHEDULE=0 */15 * * * *
- TZ=Europe/Berlin
#labels:
# - "com.centurylinklabs.watchtower.enable=true"
Nice-to-have: Filebrowser
Schone Weboberfläche um auf dem Host ein paar Daten anzuschauen. Geht auch als Mount von SMB Shares.
version: "3.8"
services:
filebrowser:
# Default User und Passwort Kombination = admin:admin
image: hurlenko/filebrowser
ports:
- 8088:8080
volumes:
# Shared remote SMB folder from a nas with healthcheck to be shown in filebrowser
- smb_nas_containers:/data/nas/containers
# Local folder to be shown in filebrowser
- /mnt/containers:/data/local/containers
- /mnt/containers/filebrowser/config:/config
environment:
- TZ=Europe/Berlin
- FB_BASEURL=/filebrowser
# Docker Default Settings
restart: unless-stopped
tty: true
# Healthcheck if mounted file exists - check local folder for file ".healthcheck"
healthcheck:
test: ["CMD", "test", "-f", "/data/nas/containers/.healthcheck"]
interval: 3s
retries: 3
start_period: 20s
timeout: 10s
# Mount Network SMB/CIFS Share
volumes:
smb_nas_containers:
driver: local
driver_opts:
type: cifs
device: //xxxx.example.com/containers
o: username=${smb_user},password=${smb_password}
Nice-to-have: System Prune (System automatisch aufräumen)
version: '3.7'
x-default-opts:
&default-opts
logging:
options:
max-size: "1m"
services:
docker-system-prune:
image: alpinelinux/docker-cli
# 86400 = 24h
command: sh -c "while true; do docker image prune -af; sleep 86400; done"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
logging:
driver: json-file
deploy:
mode: global
Nice-to-have: IT-Tools
version: '3.9'
services:
it-tools:
image: corentinth/it-tools:latest
ports:
- '5541:80'
container_name: it-tools
# Docker Default Settings
restart: unless-stopped
tty: true
Must-have: Portainer-backup
Voraussetzung: Portainer muss per http zur Verfügung stehen, sonst funktioniert es nach meinem Wissen nicht.
Hier wird nur die Portainer Instanz „gesichert“. Das „richtige“ Backup wird danach über rsync, duplicati o. ä. realisiert. Hier wird also nur ein konsistenter Applikationszustand erzeugt und abgelegt.
version: '3'
services:
portainer-backup:
container_name: portainer-backup
image: dockurr/portainer-backup:latest
# backup Backup portainer data archive
# schedule Run scheduled portainer backups
# stacks Backup portainer stacks
# test Test backup (no files are saved)
# info Get portainer server info
command: schedule
environment:
TZ: "Europe/Berlin"
PORTAINER_BACKUP_URL: "http://XXX.example.com:9000"
PORTAINER_BACKUP_TOKEN: "PORTAINER_ACCESS_TOKEN"
PORTAINER_BACKUP_IGNORE_VERSION: 1
PORTAINER_BACKUP_PASSWORD: ""
PORTAINER_BACKUP_OVERWRITE: 1
# Syntax Format:
#
# ┌──────────────────────── second (optional)
# │ ┌──────────────────── minute
# │ │ ┌──────────────── hour
# │ │ │ ┌──────────── day of month
# │ │ │ │ ┌──────── month
# │ │ │ │ │ ┌──── day of week
# │ │ │ │ │ │
# │ │ │ │ │ │
# * * * * * *
#Examples:
# 0 0 0 * * * Daily at 12:00am
# 0 0 5 1 * * 1st day of month @ 5:00am
# 0 */15 0 * * * Every 15 minutes
PORTAINER_BACKUP_SCHEDULE: "0 */15 * * * *"
PORTAINER_BACKUP_STACKS: 1
PORTAINER_BACKUP_DRYRUN: 0
PORTAINER_BACKUP_CONCISE: 50
PORTAINER_BACKUP_DIRECTORY: "/backup"
PORTAINER_BACKUP_FILENAME: "{{DATE}} portainer-backup.tar.gz"
volumes:
- /mnt/containers/portainer-backup/:/backup
Nice-to-have: Rundeck – Updates automatisieren
version: '3'
# Default login admin:admin
services:
rundeck:
image: rundeck/rundeck:SNAPSHOT
tty: true
links:
- postgres
environment:
RUNDECK_DATABASE_DRIVER: org.postgresql.Driver
RUNDECK_DATABASE_USERNAME: rundeck
RUNDECK_DATABASE_PASSWORD: rundeck
RUNDECK_DATABASE_URL: jdbc:postgresql://postgres/rundeck?autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
RUNDECK_GRAILS_URL: http://xxx.xxx.xxx.xxx:4440
volumes:
- /mnt/containers/rundeck/rundeck/data:/home/rundeck/server/data
- /mnt/containers/rundeck/rundeck/logs:/home/rundeck/var/logs
- /mnt/containers/rundeck/rundeck/etc/rundeck:/etc/rundeck/
#- ${RUNDECK_LICENSE_FILE:-/dev/null}:/home/rundeck/etc/rundeckpro-license.key
ports:
- 4440:4440
postgres:
image: library/postgres:latest
tty: true
expose:
- 5432
environment:
- POSTGRES_DB=rundeck
- POSTGRES_USER=rundeck
- POSTGRES_PASSWORD=rundeck
volumes:
- /mnt/containers/rundeck/db/postgresql:/var/lib/postgresql/data
healthcheck:
# test: ["CMD-SHELL", "pg_isready -d db-name -U db-user"]
# POSTGRES_DB & POSTGRES_USER env vars.
test: ["CMD-SHELL", "pg_isready -d rundeck -U rundeck"]
interval: 1s
timeout: 5s
retries: 10
Nice-to-have: Portainer Agent
Wenn mehrere Portainer Instanzen existieren, kann man von einer auf mehrere Docker Hostsysteme zugreifen. Dazu gibt es den Agent. Ich installiere auf jedem Docker Hostsystem Portainer.
version: '3.2'
services:
agent:
image: portainer/agent:latest
ports:
- 9001:9001
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock
- /var/lib/docker/volumes:/var/lib/docker/volumes
Nice-to-have: qrdirstat – Verzeichnisgrößen containers anschauen
version: '3'
services:
qdirstat:
image: jlesage/qdirstat
restart: unless-stopped
ports:
- "5800:5800"
volumes:
- /mnt/containers/qdirstat/config:/config:rw
- /mnt/containers:/storage:ro