Docker és Traefik beállítása staging szerveren előnézeti képe

Docker és Traefik beállítása staging szerveren

| Olvasási idő: 8 perc

Az előző bejegyzésben eljutottunk egy alapszinten konfigurált VPS-ig, amit most tovább okosítunk: telepítünk rá Docker-t és bekonfigurálunk egy Traefik-et reverse proxy-nak, automatikus SSL megújítással. Vágjunk is bele!

A Docker telepítése

A Docker telepítéséhez nincs szükségünk sok dologra, csak az alábbi parancsokat kell szépen bemásolnunk terminálba - értelmeszerűen, ahol kéri, adjuk meg a jelszavunkat:

bash
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
sudo apt update
sudo apt install docker-ce

Ellenőrizzük le, hogy működik-e a Docker:

bash
sudo systemctl status docker

Ha mindent jól csináltunk, valami ilyesmit kell visszakapnunk:

bash
docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2018-07-26 12:31:55 UTC; 1 day 23h ago
     Docs: https://docs.docker.com

Ha látjuk a loaded és active (running) szövegeket, jók vagyunk.

A későbbi munkánk megkönnyítése miatt érdemes lehet betennünk magunkat a docker csoportba, így nem kell majd sudo-t használnunk a docker parancs használatához:

bash
sudo usermod -aG docker ${USER}

Még telepítsük a Docker Compose-t is:

bash
sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose

A fenti parancsok csak példák és a Docker és a Docker Compose oldaláról származnak. Idővel elavulhatnak, így mindenképpen ellenőrizd le, hogy biztosan ezek szerepelnek-e az ottani oldalon is.

Traefik Architecture

Traefik előkészítése

A Traefik egy modern HTTP reverse proxy és load balancer Let's Encrypt támogatással, automatikus konfigurálással... Szóval a teljes marketing szöveg itt van, amire mi használni fogjuk a Traefik-et, az "automatikus" része a fenti szövegnek: az ígéret az, hogy "magától" megtalálja a futó Docker containereket és automatikusan generál nekik SSL tanúsítványt, valamint létrehoz nekik egy frontend entry point-ot, amin keresztül elérjük. Ez így már kezd izgalmassá válni, szóval haladjunk tovább.

Készítettem egy alap csomagot, amit használhatsz kiindulási pontként:

bash
git clone https://gitlab.com/webmenedzser/infrastructure_traefik.git

Lépj be az infrastructure_traefik könyvtárba, majd hozd létre a .env fájlt a következő tartalommal:

DO_AUTH_TOKEN=
TRAEFIK_PREFIX=traefik
DOMAIN=yoda.webmenedzser.hu
TRAEFIK_PORT=8080
TRAEFIK_STSPRELOAD=true
TRAEFIK_STSSECONDS=31536000

Egy kis magyarázat:

  • DO_AUTH_TOKEN: DigitalOcean token, hogy tudja manipulálni a DNS rekordokat (ehhez a DigitalOcean-nek kell a névszervernek lennie, de erre még visszatérünk),
  • TRAEFIK_PREFIX és DOMAIN együttesen azt határozzák meg, hogy milyen címen éred el a Traefik frontendet,
  • TRAEFIK_PORT a Traefik container belső portja, ezt hagyjuk így,
  • TRAEFIK_STSPRELOAD és TRAEFIK_STSSECONDS meghatározzák, hogy a fenti előálló és a proxyzott címek csak HTTPS-en keresztül érhetőek el, és ha igen, akkor az utolsó látogatástól számítva mennyi ideig legyen ez a kikötés.

Egyelőre ne indítsd el a container-t, váltsunk egy kicsit témát!

DNS és névszerver előkészítése

Ha valami oknál fogva nem szeretnéd, hogy az összes DNS rekordod között randalírozzon a Traefik, lehetőség van egy aldomainre korlátozni a játszadozásunkat, amit az alábbiak szerint tudunk megtenni.

Első lépésként vigyük az első aldomainünk névszerver kezelését DigitalOcean droplethez. Ehhez fel kell vennünk néhány rekordot a fő DNS-nél (ez nálam a Cloudflare), én ezeket állítottam be:

  • NS yoda ns1.digitalocean.com

Ezzel a yoda.webmenedzser.hu cím DNS-kezelését sikeresen eltereltük a DigitalOcean-hez. A következő lépés a DigitalOcean token beszerzése (a Write legyen bepipálva) és az alap DNS rekordok beállítása:

  • A Networking aloldalon tudsz domaint felvenni, én felvettem a yoda.webmenedzser.hu-t,
  • Az itt szereplő DNS rekordok pedig az alábbiak:
    • A *.yoda.webmenedzser.hu {{ DROPLET_IP }} (nálam 188.166.22.129), 
    • A yoda.webmenedzser.hu {{ DROPLET_IP }} 
    • NS yoda.webmenedzser.hu ns1.digitalocean.com.
    • NS *.yoda.webmenedzser.hu ns1.digitalocean.com.

Mindegyikre alacsony TTL-t állítottam be (60 másodperc), de azért eltelt egy kis idő, amíg minden névszerver átállt. Ellenőrizni a dig -t ns yoda.webmenedzser.hu és dig -t a yoda.webmenedzser.hu parancsokkal tudod az állapotot - ha ilyesmit kapsz vissza, jó vagy:

bash
;; ANSWER SECTION:
yoda.webmenedzser.hu.   60      IN      NS      digitaloceandns.webmenedzser.hu.

Ellenőrizd le a valami.yoda.webmenedzser.hu-t is - ha ott is szerepel IP cím a válaszban, akkor sikeresen beállítottad az aldomained névszerverére a DigitalOcean DNS-ét, visszatérhetünk a Traefik-hez.

A Traefik beállítása és elindítása

Ha mindent jól csináltunk, akkor a nehezén túl vagyunk, már csak néhány egyszerű feladatunk maradt.

Először is hozzunk létre egy üres fájlt acme.json néven a klónozott mappában található traefik/ mappában (ott már van egy traefik.toml fájl), majd szűkítsük le rajta a jogosultságokat:

bash
touch traefik/acme.json && chmod 600 traefik/acme.json

Ide fogja tenni a Traefik a Let's Encrypt-től kapott kulcsokat és a tanúsítványt, ha nem ezek a jogosultságok, nem fog működni a HTTPS.

Másodszor: be kell állítanunk a Traefik néhány paraméterét - ezt a traefik/traefik.toml fájlban találjuk. Nyissuk meg és a következő részeket vegyük szemügyre:

################################################################
# Entry points
################################################################
[entryPoints]
  [entryPoints.http]
  address = ":80"
    [entryPoints.http.redirect]
    entryPoint = "https"

  [entryPoints.https]
  address = ":443"
    [entryPoints.https.tls]
    [entryPoints.https.auth.basic]
      users = [
          "wbmngr:$apr1$LaK/Yskt$vvl4XZqiM3w5yDgLav2o9.",
          "client:$apr1$xiVvzfxH$sTZ3kTnv95b/puZZZdNws1",
        ]

  [entryPoints.traefik]
  address = ":8080"
    [entryPoints.traefik.auth]
      [entryPoints.traefik.auth.basic]
        users = [
          "admin:$apr1$hKyl7X0J$rOw2oUEKULVqI13vJBzHW.",
        ]

Az itt levő users tömbökbe idézőjelek közé, kettősponttal elválasztva kell beírnunk a HTTP autentikációnál használható felhasználónevet és jelszót. A fenti első példában a wbmngr + titok, illetve a client + nagyontitok párosok szerepelnek. Ilyeneket könnyedén tudsz generálni itt.

Ahogy láthatod, a HTTP rögtön átirányít HTTPS-re (mindegy, hogy milyen szolgáltatás van a Traefik mögött), a HTTPS részen pedig hitelesítést kér - így ami a Traefik mögött van, csak felhasználónév és jelszó birtokában nézhető meg. Mivel a többi szolgáltatás elé is "beül" a Traefik, ezért mindegyik mögötte levő szolgáltatást automatikusan levédi ezekkel a jelszavakkal - ez egy szinte tökéletes megoldás arra, hogy az ügyfél készülő weboldala ne legyen elérhető bárkinek.

Emellett pedig létezik még egy entry point, a traefik, ami a Traefik admin felületét védi a nagyon hatékony admin + admin párosítással. Igen, ezeket változtasd meg!

A konfiguráció még két pontjára fogok kitérni. Az első a Docker backend konfiguráció:

################################################################
# Docker configuration backend
################################################################
[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "yoda.webmenedzser.hu"
watch = true
exposedByDefault = false

Itt a domain-t kell kézzel beállítani arra a domainre, ami ebben a DNS zónában a "gyökér" (ez gyakorlatilag megegyezik a .env fájlban beállított DOMAIN változó értékével).

Egy utolsó rész, amit mindenképpen meg kell nézned:

################################################################
# Let's Encrypt settings
################################################################
[acme]
email = "[email protected]"
storage = "acme.json"
caServer = "https://acme-v02.api.letsencrypt.org/directory"
entryPoint = "https"
onHostRule = true
onDemand = false
  [acme.httpChallenge]
    entryPoint = "http"

  [[acme.domains]]
    main = "*.yoda.webmenedzser.hu"
    sans = ["yoda.webmenedzser.hu"]

  [acme.dnsChallenge]
    provider = "digitalocean"
    delayBeforeCheck = 30

Változtass e-mail címet, illetve domaineket. Megtévesztő az, hogy a main értéke nem a yoda.webmenedzser.hu, hanem a wildcard-os verzió (amiben csillag van), de ez azért van így, mert az ACME szerint a SAN nem tartalmazhat wildcard-ot.

Ha mindennel megvagy, már csak hátra kell dőlnünk, kiadnunk a infrastructure_traefik mappában a docker-compose up -d parancsot, és várni egy kicsit.

Az állapotot többféleképpen tudod ellenőrizni:

  • meg tudod nézni, szerepelnek-e a TXT rekordok a domain DNS rekordjai között,
  • vagy hogy megérkeztek-e már a tanúsítványok a Let's Encrypt-től:
bash
cat traefik/acme.json

ha a tömbben a Certificate értéke nem null, akkor a felette lévő Domain-ben szereplő domainek rendelkeznek tanúsítvánnyal,

  • valamint megnézheted a Docker container logját is:
bash
docker logs traefik

Ha itt nem szerepel ERROR, akkor alakul: ellenőrizd a traefik.DOMAIN (tehát a jelen példában a traefik.yoda.webmenedzser.hu) címet, hogy megfelelően működik-e minden. Ha feldobja a hitelesítéses dobozt, nyertél! :) Lépj be, és máris látni fogod, hogy milyen futó containereket ismert fel a Traefik (egyelőre csak önmagát), illetve a bal oldali (frontend) részben az adott frontendhez tartozó kártya Route Rule-jánál azt is láthatod, hogy milyen URL-en éred el az adott szolgáltatást (pl.: Host:traefik.yoda.webmenedzser.hu esetén az URL traefik.yoda.webmenedzser.hu lesz).

Most pedig a jutalom része következik: indítsunk el egy tetszőleges Docker container-t:

yaml
version: "3"

networks:
  infrastructure_traefik_web:
    external: true
  default:
    external: false
    
adminer:
    image: adminer:latest
    networks:
      - default
      - infrastructure_traefik_web

Fontos, hogy a docker-compose.yml fájl ebben az esetben tartalmazza a networks részeket mindkettő helyen, az infrastructure_traefik_web pedig azon a néven szerepeljen, melyen automatikusan létrejött a Traefik container elindításakor. Ez valószínűleg infrastructure_traefik_web lesz, de érdemes ellenőrizni a docker network ls paranccsal. 

Köszi a kitartást, szuper vagy! Ha még van erőd, maradt egy utolsó rész is. :)