Přejít na obsah
Aktuální kupón:sleva 10 %Uplatnit v objednávce

Docker a Docker Compose na VPS: instalace a první aplikace

Nainstalujete Docker z oficiálního repozitáře, spustíte WordPress s MariaDB přes Docker Compose a naučíte se kontejnery spravovat, aktualizovat, zálohovat a chránit firewallem.

  • pokročilý
  • ~25 min
  • Aktualizováno 1. 10. 2026

Docker spouští aplikace v izolovaných kontejnerech, které si s sebou nesou vše potřebné. Nainstalujeme ho z oficiálního repozitáře, přes Docker Compose spustíme WordPress s databází a projdeme správu, aktualizace, firewall a zálohy.

Co budete potřebovat

  • VPS u StormHostu s Ubuntu 24.04 nebo Debianem 13
  • Připojení přes SSH jako root (návod)
  • Pro WordPress s HTTPS doménu nasměrovanou na VPS
  • Asi 25 minut

Jak to funguje#

PojemCo to je
Obraz (image)Připravená šablona aplikace: systémové knihovny, program a jeho nastavení. Stahuje se z registru, nejčastěji z Docker Hubu (například wordpress, mariadb).
Kontejner (container)Běžící instance obrazu. Má vlastní souborový systém a síť, ale sdílí jádro systému s VPS. Kontejner jde kdykoli smazat a vytvořit znovu ze stejného obrazu.
VolumeTrvalé úložiště dat mimo kontejner. Data ve volume přežijí smazání i aktualizaci kontejneru. Všechno, co se má zachovat, musí být ve volume.
PortKontejner má vlastní síť. Aby byl dostupný zvenku, jeho port se „publikuje“ na port VPS.
Docker ComposeNástroj, který podle jednoho souboru compose.yaml spustí celou aplikaci složenou z více kontejnerů (například web a databázi).

Instalace#

Docker instalujte z oficiálního repozitáře Dockeru. Balíček docker.io z repozitáře distribuce bývá starší a koliduje s oficiálními balíčky.

Nejdřív odstraňte případné kolidující balíčky. Na čisté VPS příkaz nic nenajde, to je v pořádku.

Ubuntu 24.04

bash
apt remove $(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc | cut -f1)

Debian 13

bash
apt remove $(dpkg --get-selections docker.io docker-compose docker-doc docker-buildx podman-docker containerd runc | cut -f1)
  • dpkg --get-selections … – vypíše z uvedených balíčků ty, které jsou nainstalované.
  • | cut -f1 – nechá z výpisu jen názvy balíčků.
  • apt remove $(…) – odinstaluje je. Data v /var/lib/docker zůstanou.

Pak přidejte repozitář Dockeru a nainstalujte ho:

Ubuntu 24.04

bash
apt update
apt -y install 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.asc
tee /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 update
apt -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Debian 13

bash
apt update
apt -y 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
tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
apt update
apt -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Co jednotlivé řádky dělají:

PříkazCo dělá
apt -y install ca-certificates curlCertifikáty pro HTTPS a stahovací program.
install -m 0755 -d /etc/apt/keyringsVytvoří složku pro podpisové klíče repozitářů s právy 0755.
curl -fsSL …/gpg -o /etc/apt/keyrings/docker.ascStáhne podpisový klíč Dockeru. -f = při chybě HTTP skončit chybou, -s = tiše, -S = ukázat chyby, -L = následovat přesměrování.
chmod a+r …/docker.ascKlíč smí číst všichni (apt ho čte pod jiným uživatelem).
tee /etc/apt/sources.list.d/docker.sources <<EOF … EOFZapíše popis repozitáře do souboru.
Types: debRepozitář s binárními balíčky.
URIs:Adresa repozitáře pro váš systém.
Suites: $(…)Kódové jméno systému (noble pro Ubuntu 24.04, trixie pro Debian 13), doplní se samo.
Components: stableJen stabilní vydání.
Architectures: $(dpkg --print-architecture)Architektura procesoru (amd64).
Signed-By:Balíčky musí být podepsané tímto klíčem, jinak je apt odmítne.
apt -y install docker-ce …Nainstaluje Docker Engine (docker-ce), příkazový řádek (docker-ce-cli), běhové prostředí kontejnerů (containerd.io), sestavování obrazů (docker-buildx-plugin) a Compose (docker-compose-plugin).

Docker se po instalaci sám spustí a zapne po startu VPS. Ověřte instalaci:

bash
docker run --rm hello-world
docker compose version
  • docker run --rm hello-world – stáhne testovací obraz a spustí ho; --rm kontejner po skončení smaže. Uvidíte Hello from Docker!.
  • docker compose version – vypíše verzi Compose, například Docker Compose version v5.…. Po verzi 2 přešel Compose rovnou na číslo 5, starší instalace proto ukazují v2.…. Příkazy v návodu fungují v obou.

Skupina docker = práva roota

Kdo je ve skupině docker, může spouštět kontejnery s přístupem k celému disku VPS, tedy má fakticky práva roota. Do skupiny přidávejte jen lidi, kterým byste dali i root. Pokud pracujete jako root, skupinu nepotřebujete.

První aplikace: WordPress s MariaDB#

Projekt a hesla#

  1. Vytvořte složku projektu a přejděte do ní:

    bash
    mkdir -p /opt/wordpress
    cd /opt/wordpress

    Název složky (wordpress) se stane názvem projektu Compose a předponou názvů kontejnerů a volumes.

  2. Vytvořte soubor s hesly nano .env. Hesla vygenerujte v generátoru hesel (jen písmena a číslice):

    /opt/wordpress/.envini
    DB_PASSWORD=<HESLO_DATABAZE>
    DB_ROOT_PASSWORD=<HESLO_ROOT_DATABAZE>
    • DB_PASSWORD – heslo databázového uživatele WordPressu.
    • DB_ROOT_PASSWORD – heslo uživatele root uvnitř databázového kontejneru (pro zálohy a správu).
  3. Omezte čtení souboru jen na roota:

    bash
    chmod 600 .env

Soubor compose.yaml#

Vytvořte nano compose.yaml s obsahem:

/opt/wordpress/compose.yamlYAML
services:
  db:
    image: mariadb:lts
    restart: unless-stopped
    environment:
      MARIADB_DATABASE: wordpress
      MARIADB_USER: wordpress
      MARIADB_PASSWORD: ${DB_PASSWORD}
      MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      start_period: 10s
      interval: 10s
      timeout: 5s
      retries: 3

  wordpress:
    image: wordpress:latest
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "127.0.0.1:8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - wp_data:/var/www/html

volumes:
  db_data:
  wp_data:

Řádek po řádku:

ŘádekCo dělá
services:Seznam kontejnerů aplikace. Název služby (db, wordpress) slouží i jako jméno v síti projektu.
image: mariadb:ltsOficiální obraz MariaDB, značka lts = poslední verze s dlouhodobou podporou.
restart: unless-stoppedKontejner se po pádu i po restartu VPS spustí znovu, pokud jste ho sami nezastavili.
MARIADB_DATABASE, MARIADB_USER, MARIADB_PASSWORDPři prvním startu vytvoří databázi a uživatele s heslem.
MARIADB_ROOT_PASSWORDHeslo roota databáze, nastaví se při prvním startu.
${DB_PASSWORD}Hodnota se doplní ze souboru .env ve stejné složce. Hesla tak nejsou přímo v compose.yaml.
volumes: - db_data:/var/lib/mysqlData databáze se ukládají do volume db_data, takže přežijí aktualizaci kontejneru.
healthcheck:Docker každých 10 s zkontroluje skriptem healthcheck.sh z obrazu MariaDB, že databáze přijímá spojení a je inicializovaná.
depends_on: db: condition: service_healthyWordPress se spustí až ve chvíli, kdy je databáze připravená.
image: wordpress:latestOficiální obraz WordPressu (Apache + PHP).
ports: - "127.0.0.1:8080:80"Port 80 kontejneru bude dostupný na portu 8080 VPS, ale jen z VPS samotné (127.0.0.1). Zvenku se k němu dostane jen přes Nginx.
WORDPRESS_DB_HOST: dbAdresa databáze: jméno služby db v síti projektu.
WORDPRESS_DB_USER, …_PASSWORD, …_NAMEPřihlášení k databázi; musí odpovídat hodnotám u služby db.
volumes: - wp_data:/var/www/htmlSoubory WordPressu (pluginy, šablony, nahrané obrázky) jsou ve volume wp_data.
volumes: na konciDeklarace pojmenovaných volumes, které projekt používá.

Spuštění#

bash
docker compose up -d
docker compose ps
  • docker compose up -d – stáhne obrazy, vytvoří síť, volumes a kontejnery a spustí je na pozadí (-d, detached).
  • docker compose ps – vypíše kontejnery projektu a jejich stav. U db uvidíte healthy, u wordpress Up.

Kontrola z VPS: curl -I http://127.0.0.1:8080 vrátí hlavičky odpovědi WordPressu (přesměrování na instalaci).

Proměnné MARIADB_* platí jen při prvním startu

Databáze se vytvoří při prvním spuštění s prázdným volume. Pozdější změna hesla v .env heslo v databázi nezmění. Heslo změňte v databázi příkazem ALTER USER (viz MariaDB na VPS) a teprve pak v .env.

Zpřístupnění přes Nginx a HTTPS#

WordPress teď poslouchá jen na 127.0.0.1:8080. Zpřístupníte ho přes Nginx jako reverse proxy podle návodu Nginx a HTTPS: v konfiguraci použijte proxy_pass http://127.0.0.1:8080; a doménu, například blog.example.cz, a pak získejte certifikát přes certbot --nginx -d blog.example.cz.

Obraz WordPressu sám rozpozná HTTPS z hlavičky X-Forwarded-Proto, kterou Nginx podle návodu posílá. Nakonec otevřete https://blog.example.cz a dokončete instalaci WordPressu v prohlížeči.

Správa kontejnerů#

Příkazy docker compose spouštějte ve složce projektu (cd /opt/wordpress).

PříkazCo dělá
docker compose psStav kontejnerů projektu.
docker compose logs -fVýpis logů všech služeb; -f = sledovat průběžně (ukončíte Ctrl+C). Jen jedna služba: docker compose logs -f wordpress.
docker compose restartRestartuje kontejnery.
docker compose stop / startZastaví / spustí kontejnery, nic nemaže.
docker compose up -dPo změně compose.yaml vytvoří znovu jen změněné kontejnery.
docker compose downZastaví a smaže kontejnery a síť. Volumes s daty zůstanou.
docker compose exec db mariadb -uroot -pSpustí příkaz uvnitř běžícího kontejneru (tady konzoli MariaDB).
docker compose configZkontroluje compose.yaml a vypíše ho s doplněnými hodnotami z .env (pozor, ukáže i hesla).

Aktualizace na nové verze obrazů:

bash
docker compose pull
docker compose up -d
docker image prune -f
  • docker compose pull – stáhne nové verze obrazů.
  • docker compose up -d – vytvoří znovu kontejnery, které mají novější obraz. Data ve volumes zůstanou.
  • docker image prune -f – smaže staré, už nepoužívané obrazy; -f bez potvrzení.

docker compose down -v smaže data

Přepínač -v u docker compose down smaže i volumes projektu, tedy databázi a soubory WordPressu. Nejde to vrátit. Používejte ho jen tehdy, když chcete aplikaci odstranit úplně a máte zálohu.

Možnosti nastavení restart::

HodnotaKdy se kontejner spustí znovu
noNikdy (výchozí).
alwaysVždy, i když jste ho ručně zastavili (po restartu Dockeru nebo VPS).
on-failureJen když skončí chybou.
unless-stoppedVždy, kromě případu, kdy jste ho zastavili sami. Doporučeno pro služby.

Porty a firewall#

Docker publikuje porty kontejnerů vlastními pravidly firewallu, která obcházejí UFW. Port publikovaný jako 8080:80 je dostupný z internetu, i když ho v UFW nepovolíte. Podrobně to vysvětluje návod Firewall UFW.

Zápis v ports:Kdo se na port dostane
"8080:80"Kdokoli z internetu, bez ohledu na UFW.
"127.0.0.1:8080:80"Jen procesy na VPS (například Nginx). Doporučeno pro weby za Nginxem.
bez ports:Jen ostatní kontejnery ve stejné síti projektu (typicky databáze).

Databázi a další interní služby nepublikujte vůbec. Porty, které mají být veřejné (například herní server v kontejneru), omezujte firewallem v zákaznické zóně (návod). Ten stojí před VPS a Docker ho obejít nemůže.

Úklid místa na disku#

Obrazy, zastavené kontejnery a logy časem zaberou hodně místa.

bash
docker system df
docker system prune
  • docker system df – kolik místa zabírají obrazy, kontejnery, volumes a cache.
  • docker system prune – po potvrzení smaže zastavené kontejnery, nepoužívané sítě, obrazy bez názvu a cache sestavování. Volumes s daty bez přepínače --volumes nemaže.

Opatrně s mazáním volumes a s -a

docker system prune --volumes smaže i nepoužívané anonymní volumes (bez jména, vznikají například při docker run bez -v). Pokud v nich byla data kontejneru, který je zrovna smazaný nebo zastavený, jsou pryč. docker volume prune -a smaže i pojmenované volumes jako wordpress_db_data, když je nepoužívá žádný kontejner, například po docker compose down. docker system prune -a smaže všechny obrazy, které nepoužívá žádný kontejner. Před potvrzením si přečtěte, co příkaz vypíše, že smaže.

Logy kontejnerů se ve výchozím nastavení neotáčejí a můžou zaplnit disk. Nastavte ovladač local, který staré logy maže sám (ve výchozím stavu drží nejvýš 5 souborů po 20 MB na kontejner). Vytvořte soubor nano /etc/docker/daemon.json s obsahem níže. Pokud soubor už existuje, nepřepisujte ho, jen do něj doplňte řádek "log-driver" (položky oddělené čárkou):

/etc/docker/daemon.jsonJSON
{
  "log-driver": "local"
}

Pak restartujte Docker (systemctl restart docker) a kontejnery vytvořte znovu (docker compose up -d --force-recreate). Nastavení platí jen pro nově vytvořené kontejnery.

Zálohy#

Zálohujte volumes, ne kontejnery. Kontejner vytvoříte znovu z obrazu, data ne.

  1. Vytvořte složku pro zálohy: mkdir -p /root/zalohy.

  2. Databázi zálohujte exportem (konzistentnější než kopie souborů):

    bash
    cd /opt/wordpress
    docker compose exec -T db sh -c 'exec mariadb-dump --single-transaction --all-databases -uroot -p"$MARIADB_ROOT_PASSWORD"' > /root/zalohy/wp-db-$(date +%F).sql
    • docker compose exec -T db – spustí příkaz v kontejneru db; -T vypne terminál, aby šel výstup přesměrovat do souboru.
    • sh -c '…' – příkaz proběhne v shellu kontejneru, kde je proměnná $MARIADB_ROOT_PASSWORD nastavená.
    • mariadb-dump --single-transaction --all-databases – export všech databází bez zamykání.
    • > /root/zalohy/… – výstup se uloží na VPS mimo kontejner.
  3. Soubory WordPressu zálohujte zabalením volume:

    bash
    docker run --rm -v wordpress_wp_data:/data:ro -v /root/zalohy:/backup alpine tar czf /backup/wp-files-$(date +%F).tar.gz -C /data .
    • docker run --rm – spustí jednorázový kontejner, který se po skončení smaže.
    • -v wordpress_wp_data:/data:ro – připojí volume wp_data projektu wordpress jen pro čtení (ro).
    • -v /root/zalohy:/backup – připojí složku záloh z VPS.
    • alpine tar czf … -C /data . – v malém obrazu Alpine zabalí obsah volume do archivu.

    Přesné názvy volumes vypíše docker volume ls.

Automatické spouštění záloh cronem a jejich přenos mimo VPS popisuje návod Zálohy na VPS.

Ověření#

  • docker compose ps ukazuje oba kontejnery jako běžící, databázi jako healthy.
  • https://blog.example.cz zobrazí WordPress se zámkem v adresním řádku.
  • Po restartu VPS (reboot) se kontejnery spustí samy.
  • Z jiného počítače se na http://<IP_ADRESA_VPS>:8080 nepřipojíte (port je jen na 127.0.0.1).

Když něco nefunguje#

permission denied while trying to connect to the Docker daemon socket#

Nejste root a váš uživatel není ve skupině docker. Spusťte příkaz přes sudo, nebo se přihlaste jako root.

Bind for 127.0.0.1:8080 failed: port is already allocated nebo address already in use#

Port 8080 už používá jiný kontejner (první hláška) nebo jiný program na VPS (druhá hláška). Zjistěte který (ss -tlnp | grep 8080, docker ps) a v compose.yaml zvolte jiný port, například 127.0.0.1:8081:80. Pak upravte i proxy_pass v Nginxu.

WordPress hlásí „Error establishing a database connection“#

Databáze ještě není připravená nebo nesedí přihlašovací údaje. Podívejte se do logu databáze (docker compose logs db). Pokud jste měnili heslo v .env až po prvním startu, databáze má pořád staré heslo (viz upozornění v kapitole Spuštění).

Kontejner je stále ve stavu Restarting#

Aplikace v kontejneru hned po startu padá. Příčinu najdete v logu: docker compose logs --tail 50 <NAZEV_SLUZBY>.

toomanyrequests: You have reached your unauthenticated pull rate limit#

Docker Hub omezuje stahování obrazů bez přihlášení na 100 za 6 hodin z jedné IP adresy. Počkejte, nebo se přihlaste svým účtem Docker Hubu: docker login.

no space left on device#

Došlo místo na disku. Zjistěte, co ho zabírá (docker system df, df -h), a ukliďte podle kapitoly Úklid místa na disku. Pokud místo opravdu chybí, navyšte RAM v záložce Změna balíčku, disk roste s pamětí.

Shrnutí

  • Docker instalujte z oficiálního repozitáře download.docker.com, ne balíček docker.io.
  • Data patří do volumes; kontejnery jde kdykoli smazat a vytvořit znovu.
  • Weby publikujte na 127.0.0.1 a zpřístupněte přes Nginx s HTTPS; Docker jinak obchází UFW.
  • Aktualizace: docker compose pull a docker compose up -d.
  • docker compose down -v a prune --volumes mažou data, zálohujte volumes pravidelně.

Hledání v návodech