Docker host telepítése (22.04 LTS)
Ebben a leírásban alaptelepített és biztosított szervergépen Docker host környezetet alakítunk ki, amely több, egymástól független standalone (nem orkesztrált) Docker szolgáltatás (a továbbiakban service) futtatását és (manuális) menedzselését biztosítja.
Megjegyzés: a standalone megközelítés a cloud világában elavultnak tűnik, azonban - nézetem szerint - kisvállalati környezetben lehet létjogosultsága.
Tartalomjegyzék
Docker (standalone hosting, farm) házirend
Ebben a leírásban egy standalone szervergépen (nem swarm-ban) futtatunk egymástól független dockerezett szolgáltatásokat.
- A szolgáltatásokat egy közös, nem sudo-képes, dedikált Linux felhasználó (dockeradmin) nevében futtatjuk.
- A szolgáltatásokat kiszolgáló közös scriptek a dockeradmin HOME/bin könyvtárában találhatóak.
- A szolgáltatásokhoz kapcsolódó valamennyi egyedi állomány (specifikus kód, karbantartó script, konfiguráció, adat, helyi mentés, log, stb.) egyetlen könyvtárszerkezetben, a dockeradmin $HOME/services/<szolgáltatás neve> könyvtárban (szolgáltatáskönyvtár) található.
- A szolgáltatáskönyvtárak azonos skeletonból jönnek létre.
- Minden szolgáltatást egy-egy, a szolgáltatáskönyvárban megtalálható docker-compose.yml állomány definiál.
- A szolgáltatások számára a szervergép
- közös külső IP-t,
- hálózati forgalomirányítást,
- közös web reverse proxyt,
- SMTP smarthostot (technikai levelezést) és
- periodikus (napi) mentést (DB dump, fájlterület time machine (git) vagy tar.gz) biztosít.
TODO!
Reverse web proxy telepítése
Amennyiben a telepítés alatti szervergépen még nincs telepítve webszerver, és a leendő szolgáltatások publikus web interface-szel fognak rendelkezni (ez utóbbi csaknem bizonyos), opcionálisan (de erősen javasoltan) érdemes egy professzionális webszervert reverse proxyként telepíteni a https tanúsítványok egyszerűbb kezelése és a könnyebb biztosíthatóság miatt. A jelen leírásban használandó skeleton az Apache 2 illetve az nginx webszerverekkel képes jól együttműködni.
nginx telepítése reverse web proxyként
Az nginx a szokásos módon telepíthető:
sudo apt install nginx --no-install-recommends
Sajnos a telepítés egy hiba miatt elakad, ha az IPv6 le van tiltva. Áthidaló megoldásként, miután a telepítő elakadt, szerkesszük meg az ekkor már telepített /etc/nginx/sites-available/default állományt:
sudo mcedit /etc/nginx/sites-available/default
és az elején kommentezzük ki az IPv6-os listen sort:
[...] server { listen 80 default_server; # listen [::]:80 default_server; [...]
Ezután a telepítő parancsot ismét kiadva:
sudo apt install nginx --no-install-recommends # no, még egyszer!
a telepítés már hibátlanul végigmegy. A webszerver futását a
sudo systemctl status nginx
paranccsal verifikálhatjuk.
A publikus webszolgáltatáshoz szükséges még a bejövő webforgalom beengedése a csomagszűrő tűzfalon:
sudo ufw allow "Nginx Full"
Gyorstesztként web böngészőprogramban kérjük el a http://IP.IP.IP.IP/ weboldalt (ahol IP.IP.IP.IP a telepítés alatt álló szervergép publikus IP címe, vagy egy erre mutató DNS hostnév) - az nginx alapértelmezett weboldalát kell látnunk.
Egyéb csomagtelepítések
A Docker skeletonnak szüksége van az alábbi, eddig még nem telepített segédeszközökre:
sudo apt install git metastore socat # a git általában már telepített, a teljesség kedvéért szerepel itt
Fentiek további beállítást nem igényelnek.
A Docker telepítése
A Docker (community edition) telepíthető az Ubuntu repositoryból (docker.io, Debian way), vagy a docker.com repositoryból (docker-ce, Golang way). A fő különbség, hogy a docker.ce statikusan linkelt (az összes függőségével egybecsomagolva érkezik), míg a docker.io esetében a függőségeket a Debian/Ubuntu kezeli (ami jelentős erőfeszítést igényel a maintainer-től). A Debian-way mellett szólhat a kiterjedtebb security- és tesztelési mechanizmus; ellene szólhat a kétely, hogy képes lesz-e lépést tartani a Docker kiadásaival az LTS támogatás teljes időtartamában.
Mivel mindkét kiadás egyazon operációs rendszer alá nem telepíthető, választanunk kell közülük. Jelen leírásban a Debian way-t preferálom.
docker.io
A szokásos módon telepíthető:
sudo apt install docker.io docker-compose # Sok függőség, elsősorban Python
Ellenőrizzük, hogy elindult-e a szolgáltatás:
sudo systemctl status docker
Ha nem indulna el, engedélyezni kell, majd manuálisan indítható:
sudo systemctl enable --now docker sudo systemctl status docker # újabb ellenőrzés sudo systemctl start docker # ha nem futna
Fentiek után az engine elindul, és a szervergép újraindításakor is automatikusan futni kezd.
docker-ce
TODO!
Docker alapbeállítások
Tűzfalbeállítások (UFW) módosítása a Docker használatához
Két lényeges problémát kell kezelnünk:
- Alapértelmezésben az UFW blokkolja a szolgáltatások (Docker image-ek) kommunikációját a host gépen futó szolgáltatásokkal (pl. levélküldés a host MTA-n keresztül). Engedélyezzük a szolgáltatások alhálózatairól és a host gép közötti forgalmat korlátozások nélkül (átgondolni: TODO!):
sudo ufw allow in from 172.17.0.0/16 to any comment 'From services to host' sudo ufw allow out from any to 172.17.0.0/16 comment 'From host to services'
- Alapértelmezésben a Docker által exportált portok kívülről láthatóak lesznek annak ellenére, hogy az UFW-ban nem engedélyeztük ezeket az in szabályokban. Ennek megoldására az innen származó (3rd party) ufw-docker scriptet alkalmazzuk, amely a routing átkonfigurálásával tiltja a fenti forgalmat.
Töltsük le a projekt legfrissebb verzióját, és a .zip-ből az ufw-docker állományt másoljuk a /usr/local/sbin könyvtárba, majd adjuk a root tulajdonába, és adjunk rá végrehajtási jogot:
sudo chown root:root /usr/local/sbin/ufw-docker sudo chmod 750 /usr/local/sbin/ufw-docker
Ezután telepíttessük a scripttel a routing szabályokat, majd aktiváljuk azokat az UFW újraindításával:
sudo ufw-docker install sudo systemctl restart ufw
A script csak a /etc/ufw/rules.after állományt módosítja (előtte az eredeti állapotot elmenti). Telepítés után a scriptet csak akkor kell használnunk, ha a blokkolt forgalmak valamelyikét engedélyezni szeretnénk (bővebben ld. a README.md leírást a fenti weboldalon, vagy a letöltött .zip-ben).
Gyorsteszt: TODO!
Levélküldés engedélyezése a dockerezett szolgáltatások számára
Hasznos lehet, ha a szolgáltatások is igénybe vehetik a korábban beállított technikai levélküldést. Ehhez engedélyezzük a mail relay-t a Postfixben a Docker network-ök felől is:
sudo mcedit /etc/postfix/main.cf
[...] mynetworks = 127.0.0.0/8 172.16.0.0/12 [...] [...]
A változtatást a Postfix újraindításával érvényesítsük:
sudo systemctl restart postfix
A dockeradmin felhasználó és tárhely elkészítése
Ebben a leírásban a Docker szolgáltatások tárhelyeit a szolgáltatásokat menedzselő, közös Linux felhasználó HOME-jában (/srv/docker) alakítjuk ki. Ennek a tárhelynek megfelelő méretű, futtathatóan és írható-olvashatóan csatolt partíción kell lennie.
A dockeradmin lényegét tekintve rendszer felhasználó, a gyakorlatban azonban rendszergazdák (emberek) fogják nevében belépve a szolgáltatások karbantartási műveleteit elvégezni. A belépéshez mindenkitől külön-külön (magán) SSH kulcsot fogunk kérni.
- Hozzuk létre a felhasználót az alábbi (sudo-képes felhasználóként - sysadminként - kiadott) parancsokkal:
sudo adduser --gecos "Docker Administrator" --home /srv/docker dockeradmin # kér egy jelszót a felhasználó számára
A jelszó lehetőleg ne triviális, preferáltan generált legyen (pl. innen). A jelszót csak a sudo-hoz fogjuk használni (mivel a jelszóval belépést SSH-n letiltottuk, használatával csak a virtuális konzolon lehet belépni).
- Adjuk hozzá a dockeradmin-t a Docker kezelésére sudo nélkül is jogosultak csoportjához. A házirendtől eltérően jelenleg a Docker adminisztrátor számára is szükséges a sudo, a host és a szolgáltatások fájlrendszeri jogosultságainak egyeztetése miatt (TODO!):
sudo usermod -aG docker,sudo dockeradmin # beállítás sudo groups dockeradmin # ellenőrzés
- Tegyük priváttá a felhasználó HOME könyvtárát:
export user='dockeradmin' home='/srv/docker' sudo chmod -R o-rwx $home sudo chmod g+rwx $home # feleljen meg az UMASK-nak sudo chmod o+x $home # szüksége lehet rá a Dockeren belül futó szolgáltatásoknak sudo ls -lad $home # drwxrwx--x dockeradmin dockeradmin /srv/docker
- Módosítsuk a felhasználó profilbeállításait:
sudo mcedit $home/.profile
Szúrjuk be a file végére:
# Custom editor. export EDITOR="/usr/bin/mcedit" # More parseable ls -la format. export TIME_STYLE="long-iso"
Megjegyzés: a szövegszerkesztő választása természetesen opcionális - bár az alaptelepített nano teljesen használható, részemről az mcedit-et preferálom.
- Készítsük elő a dockeradmin számára a nyilvános kulcsú távoli bejelentkezéshez szükséges állományokat:
sudo mkdir $home/.ssh; sudo chown $user:$user $home/.ssh sudo touch $home/.ssh/authorized_keys; sudo chown $user:$user $home/.ssh/authorized_keys
Amennyiben vannak publikus kulcsaink a dockeradmin felhasználóként történő bejelentkezéshez, töltsük fel és másoljuk be azokat az authorized_keys állományba (ha nincs kulcsunk, csak a virtuális konzolon tudunk dockeradmin-ként bejelentkezni!). Ezután zárjuk le ezt az állományt:
sudo chmod 400 $home/.ssh/authorized_keys sudo chattr +i $home/.ssh/authorized_keys sudo chmod 500 $home/.ssh/
A fenti beállításokkal már csak a root tud a dockeradmin felhasználó nevében történő bejelentkezéshez szükséges kulcsokat felvenni (az immutable bit levétele után).
- Mivel a dockeradmin alapvetően nem szokványos felhasználó, nem hagyjuk, hogy a shelljére vonatkozó beállításokat megváltoztassa:
sudo chmod 440 $home/.bashrc; sudo chattr +i $home/.bashrc sudo chmod 440 $home/.bash_logout; sudo chattr +i $home/.bash_logout sudo chmod 440 $home/.profile; sudo chattr +i $home/.profile
Ezzel a felhasználót és a tárhelyet előkészítettük.
A Docker skeleton telepítése
A skeleton telepítéséhez (és minden további, a Docker szolgáltatásokkal kapcsolatos művelet elvégzéséhez) jelentkezzünk be dockeradmin felhasználóként!
Docker gyorsteszt
Első lépésként futtassuk le a hello-world példa image-et:
docker run hello-world
Siker esetén a Docker alapfunkciói használhatóak, a teszt containert törölhetjük:
docker system prune
Szükséges mappák és beállítások
Hozzuk létre a bin, services és tmp mappákat:
mkdir $HOME/bin $HOME/tmp mkdir $HOME/services; chmod o+x $HOME/services; setfacl -d -m u:$USER:rwX,g::rwX $HOME/services
Az ACL-lel azt szeretnénk biztosítani, hogy a szolgáltatásmappák hierarchiájára a dockeradmin (user és group) mindig rendelkezzen írásjoggal, továbbá hogy ez a hierarchia a szolgáltatások belső felhasználói számára is bejárható legyen (átgondolni: TODO!).
Fentieken kívül:
- A Midnight Commanderben hasznos beállítani (mc, F9, Beállítások, Alapbeállítások) a saját szövegszerkesztő használatát (F9, Beállítások, Saját szövegszerkesztő, OK).
- Az mcedit-ben (F9, Beállítások, Általános) az új sorban automatikus behúzást (ha be lenne kapcsolva) és a látható tabulátorokat(!) kikapcsolni, végül az mc beállításokat elmenteni (F9, Beállítások, Beállítások mentése).
A technikai levelezés beállítása
Amennyiben a szervergép biztosít technikai levelezést, állítsuk be a dockeradmin felhasználónak küldött levelek továbbítását a Docker adminisztrátorok tényleges email címeire. Ehhez:
- Küldjünk egy teszt levelet (dockeradmin-ként bejelentkezve):
echo 'Teszt' | mail -s 'Teszt' valid@email.address
- Siker esetén állítsuk be a levéltovábbítást a $HOME/.forward állományban:
mcedit $HOME/.forward
dockeradmin1@email.cime dockeradmin2@email.cime [...]
- Ellenőrizzük a levéltovábbítást:
echo Teszt | mail -s Teszt dockeradmin
Siker esetén ezután meg fogjuk kapni a Docker környezetek által küldött technikai leveleket is.
Opcionálisan, amennyiben a dockeradmin nem sudo-képes (TODO!), lezár(at)hatjuk a .forward állományt, megakadályozva ezzel, hogy a címlistát valamelyik Docker adminisztrátor (vagy egy dockeradmin-ként futó malware) törölje vagy módosítsa. Ehhez sudo-képes felhasználóként (pl. sysadminként) bejelentkezve adjuk ki az alábbi parancsokat:
export home='/srv/docker' sudo chmod 400 $home/.forward sudo chattr +i $home/.forward
Ezután a címlista már csak root-ként módosítható (az immutable bit levétele után).
A skeleton telepítése
Az egyes szolgáltatásokat egy közös skeletonból fogjuk kialakítani, amely tartalmaz csak egyszer telepítendő, server-wide elemeket is - ezek némelyikéhez szükséges a sudo jog!
- Töltsük le (TODO!) a skeleton legfrissebb (tömörített, .tgz) változatát, célszerűen a $HOME/tmp könyvtárba;
- Alkalmazzuk a skeletonbeli .templates beállításait:
- A skeleton .templates/bin könyvtárának tartalmát másoljuk a $HOME/bin könyvtárba;
- Amennyiben a szervergép nem biztosít technikai levelezést, adjunk futtatási jogot a $HOME/bin/mail (dummy) állományra (biztosítva ezzel, hogy a mail parancsot függőségként tartalmazó scriptek ennek ellenére lefussanak):
chmod ug+x $HOME/bin/mail
- Amennyiben a szervergépen nginx webszerver fut:
- A skeleton .templates/nginx/.nginx könyvtárát másoljuk be a $HOME/services könyvtárba (a .gitignore törölhető);
- A skeleton .templates/nginx/conf.d könyvtárának tartalmát másoljuk be a /etc/nginx/conf.d könyvtárba és adjuk a root tulajdonába 640-es jogosultságokkal (ehhez sudo szükséges!);
- Amennyiben a webszervert más szolgáltatás nem használja, töröljük a /etc/nginx/sites-enabled/default symlinket (ehhez sudo szükséges!) - ezzel átvesszük az alapértelmezett weboldal szolgáltatását is;
- A skeleton .templates/sudoers.d tartalmát másoljuk be a /etc/sudoers.d könyvtárba és adjuk a root tulajdonába 440-es jogosultságokkal (ehhez sudo szükséges!);
- Olvastassuk újra a webszerver konfigurációját (a sudoers.d beállítás miatt ehhez nem kell sudo):
- nginx esetén
systemctl reolad nginx
- Apache 2 esetén
systemctl reload apache2
- nginx esetén
- Állítsuk be az időzített karbantartások lefuttatását:
crontab -e
Másoljuk a fájl végére a skeletonbeli .templates/crontab tartalmát és mentsük el az új contab állományt.
Ezzel a skeleton server-wide elemeit telepítettük, készen állunk az első szolgáltatás létrehozatalára.
Karbantartások
TODO!
Irodalom
- How to Install Docker On Ubuntu 20.04 LTS Focal Fossa (Linuxconfig.org)
- Install Docker Engine on Ubuntu (Docker Docs)
- What is docker.io in relation to docker-ce and docker-ee? (StackOverflow)
- The docker.io Debian package is back to life (Collabora)
- Post-installation steps for Linux (Docker Docs)
- To Fix The Docker and UFW Security Flaw Without Disabling Iptables (GitHub)