19/02/2025
nginx proxy
Pokud používáte docker a potřebujete mít na svém serveru více webů či webových aplikací jak jednu, potřebujete něco, co určí kam se bude směřovat příchozí požadavek z klienta tedy prohlížeče uživatele. Něco musí jasně říci, zda daná doména či subdoména směřuje na projekt a, b nebo c. Toto něco je reverzní proxy. Já si zde pro své budoucí já udělám několik poznámek, jak jsem takovou reverzní proxy rozchodil pro webový server nginx.
Na začátek se hodí říci, že těch způsobů je mnoho. Dokonce bych řekl, že až moc. Vlastně již v základu samotný webový server nginx lze údajně nakonfigurovat jako reverzní proxy. To znamená, že by teoreticky mělo stačit nainstalovat webový server a trochu, tedy možná trochu více ho nakonfigurovat. Mě to ve světě dockeru, kde se spoléháme na uzavřené boxy a modlíme se, aby v nich kromě deklarovaného nebylo i něco nepěkného, přišlo tak nějak složité.
Nakonec jsem našel již připravené kontejnery, které celou proxy včetně zajištění https přes SSL certifikát umí dělat automaticky. Těmi kontejnery je nginxproxy/nginx-proxy a nginxproxy/acme-companion.
Níže představím příklad se třemi weby. Jeden web bude na doméně prvního řádu, druhý bude na subdoméně a třetí bude na jiné doméně prvního řádu. Vše poběží na jednom serveru s dockerem. Příklad předpokládá nainstalovaný docker a docker compose.
proxy
Nejdřív postavíme samotnou proxy:
Pomocí terminálu vytvoříme adresar nginx-proxy a v něm založíme soubor docker-compose.yml.
$ mkdir nginx-proxy $ cd nginx-proxy/ $ vim docker-compose.yml
docker-compose.yml
services:
nginx-proxy:
image: nginxproxy/nginx-proxy:1.5.0
container_name: nginx-proxy
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./html:/usr/share/nginx/html
- ./certs:/etc/nginx/certs
- ./vhost:/etc/nginx/vhost.d
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
- "net"
nginx-proxy-acme:
image: nginxproxy/acme-companion:2.2.10
container_name: nginx-proxy-acme
restart: always
volumes_from:
- nginx-proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme:/etc/acme.sh
environment:
- DEFAULT_EMAIL=muj@email.cz
networks:
net:
external: true
Pro kontejner nginx-proxy jsou definovány tři svazky:
/etc/nginx/certs pro ukládání certifikátu a soukromých klíčů
/etc/nginx/vhost.d pro změnu konfigurace vhost z důvodu přístupu certifikační autority k http-01 souborům
/usr/share/nginx/html pro zápis samotných http-01
Pro kontejner acme-companion pak ještě:
/etc/acme.sh pro ukládání konfigurace a stavu
Všechny kontejnery, které má reverzní proxy spravovat musí být pod stejnou sítí. V tomto příkladě pod sítí “net”. Email se zadává kvůli certifikační autoritě Let’s Encrypt, pro možnost kontaktování admina serveru. Verze jednotlivých kontejnerů upravte na poslední aktuální. Obecně se nedoporučuje používat kontejnery označené “last” s ohledem na stabilitu. Lepší je provádět řízené aktualizace.
Nyní nahoďte kontejner pomocí $ docker compose up a pokud vše proběhne správně, nemělo by to vyhodit žádně chyby. Pokud je tomu tak, shoďte ctrl+c a opět nahoďte na pozadí $ docker compose up -d (pokud nemáte povoleno spouštění dockeru pod uživatelem nezapomeňte přejít pod roota nebo použít sudo).
samotné webové aplikace/weby
Obdobným způsob vytvoříme i tři kontejnery s weby/aplikacemi.
- projekt 1:
$ cd $ mkdir projekt1 $ cd projekt1/ $ vim docker-compose.yml
docker-compose.yml
services:
web:
image: nginx:1.25.3
container_name: projekt1
environment:
- VIRTUAL_HOST=domena.cz
- LETSENCRYPT_HOST=domena.cz
restart: always
volumes:
- ./html:/usr/share/nginx/html
networks:
- "net"
networks:
net:
external: true
$ docker compose up -d
- projekt 2:
$ cd $ mkdir projekt2 $ cd projekt2/ $ vim docker-compose.yml
docker-compose.yml
services:
paste:
image: privatebin/fs:1.7.1
container_name: projekt2
environment:
- VIRTUAL_HOST=paste.domena.cz
- LETSENCRYPT_HOST=paste.domena.cz
restart: always
volumes:
- ./privatebin-data:/srv/data
- ./conf.php:/srv/cfg/conf.php:ro
networks:
- "net"
read_only: true
networks:
net:
external: true
$ docker compose up -d
- projekt 3:
$ cd $ mkdir projekt3 $ cd projekt3/ $ vim docker-compose.yml
docker-compose.yml
services:
web:
image: nginx:1.25.3
container_name: projekt3
environment:
- VIRTUAL_HOST=druhadomena.cz
- LETSENCRYPT_HOST=druhadomena.cz
restart: always
volumes:
- ./html:/usr/share/nginx/html
networks:
- "net"
networks:
net:
external: true
$ docker compose up -d
Z výše uvedeného je zřejmé, že každý web/aplikace, kterou chcete na serveru provozovat musí mít nastavené hodnoty environment VITRUAL_HOST a LETSENCRYPT_HOST, které udávají přiřazení dané domény či subdomény k tomu danému kontejneru. Současně všechny kontejnery musí mít nastavenou společnou síť, která je stejná jako sít u kontejneru s nginx-proxy (v příkladu síť “net”).
Zvolené příklady ukazují obyčejný web server na doméně “domena.cz” a “druhadomena.cz”. Dále pak aplikaci privatebin (pastebin) na subdoméně “paste.domena.cz”.
Toť vše. Hotovo! Je možné, že při prvním načtení webu nebude fungovat https. Pokud se tak stane, napočítejte v duchu do šedesáti a obnovte stránku. Mělo by být vše v pořádku.
odkazy
https://hub.docker.com/r/nginxproxy/nginx-proxyhttps://hub.docker.com/r/nginxproxy/acme-companion
error 413 request entity too large
Chyba 413 značí, že uploadovaný soubor je moc velký a že ho nginx nepustí. Nginx-proxy má limit na velikos hodně nízko. Proto ve většině případů, kdy potřebujeme nahrát na server přes formulář nějaký soubor, musíme tento limit zvýšit. Běžně se toto dělá v configuračním souboru nginx serveru. V našem případě je však tento soubor v proxy generovaný. Řeší se to tedy přidáním cofigurace do souboru ./vhost/default.
./vhost/default
client_max_body_size 50m;
50m nastaví limit na 50MB. Pokud by se nastavilo místo toho 0, bylo by nahrávání bez limitu.
aktualizace článku
28.10.2024:
- upraveny configurační soubory docker-compose.yml - odstraněny řádky s verzí, docker je už nechce
- přidán odstavec o chybě 413