Nginx, PHP-FPM und Let’s Encrypt per Docker-Compose aufsetzen
Um einen LAMDA Server einfach aufzusetzen, wie in meinem Fall auf Amazon EC2, geht es am Einfachsten mit Docker-Compose. Damit lassen sich die einzelnen Container schnell aktualisieren und System unabhängig betreiben.
Als Erstes installieren wir auf der neuen EC2 Instanz (ich verwende ein Ubuntu 18.4) gewisse Dinge:
apt update && apt upgrade apt install -y mysql-client curl python unzip
Ich installiere alles in das /opt Verzeichnis und erstelle dazu diverse weitere Verzeichnisse die benötigt werden:
mkdir -p /opt/www/cache /root/.aws /opt/www/log/certbot /opt/www/log/nginx /opt/www/log/php /opt/www/certbot/conf /opt/www/certbot/www
Jetzt installieren wir Docker und Docker-Compose.
apt-get install -y apt-transport-https ca-certificates gnupg-agent software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" apt-get update apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose
Als nächstes benötigen wir je nach gewünschten Diensten die Dockerfiles:
/opt/docker/php/Dockerfile:
FROM php:fpm-alpine RUN apk update && apk add --no-cache python sudo && docker-php-ext-install mysqli &&\ mkdir -p /var/log/php /etc/nginx/cache /root/scripts
/opt/docker/nginx/Dockerfile:
FROM nginx:alpine RUN apk update && apk add --no-cache logrotate &&\ mkdir -p /var/log/nginx /etc/nginx/cache /var/www/certbot
Die beiden Container müssen wir nun erstellen:
cd /opt/docker/nginx/ docker build --progress=plain -t my-nginx --force-rm -f Dockerfile . cd /opt/docker/php/ docker build --progress=plain -t my-php --force-rm -f Dockerfile .
Nun können bereits die Webdateien in das Verzeichnis /opt/www kopiert werden.
Leider startet der Nginx nicht ohne Zertifikate. Let's Encrypt kann aber Zertifikate nur ausstellen bei lauffähigem Nginx. Daher erstellen wir einmalige Wegwerf-Self-Signed-Zertifikate für jede Domain die wir nutzen wollen:
openssl rand -writerand /root/.rnd mkdir -p /opt/www/certbot/conf/live/FULLDOMAINNAME openssl req -x509 -nodes -newkey rsa:1024 -days 90 -keyout '/opt/www/certbot/conf/live/FULLDOMAINNAME/privkey.pem' -out '/opt/www/certbot/conf/live/FULLDOMAINNAME/fullchain.pem' -subj '/CN=localhost' rm /root/.rnd
Wir erstellen folgendes Script /opt/www/certbot/conf/start.sh und ersetzen FULLDOMAINNAME wieder überall
if [ ! -d "/opt/www/certbot/conf/accounts" ]; then echo "No Lets Encrypt Account found, wait 5s and start getting Certifications..." sleep 5s mv /etc/letsencrypt/live/FULLDOMAINNAME /etc/letsencrypt/live/FULLDOMAINNAME-tmp certbot certonly --webroot -w /var/www/certbot --email marketing@sintratec.com --no-eff-email -d FULLDOMAINNAME --cert-name FULLDOMAINNAME --rsa-key-size 4096 --agree-tos --force-renewal --expand --allow-subset-of-names if [ ! -d "/etc/letsencrypt/live/staging.sintratec.com" ]; then mv /etc/letsencrypt/live/FULLDOMAINNAME-tmp /etc/letsencrypt/live/FULLDOMAINNAME.com else rm -R /etc/letsencrypt/live/FULLDOMAINNAME-tmp fi fi
Und geben ihm Ausführrechte:
chmod 740 /opt/www/certbot/conf/start.sh
Was nun noch fehlt, sind die Konfigurationsdateien, welche man hier für PHP und Nginx runterladen kann: etc.zip, was ins /opt Verzeichnis entpackt werden kann. Im Nginx sites/ Ordner, müssen noch die entsprechenden Domains eingetragen werden, welche ausgeliefert werden sollten (siehe FULLDOMAINNAME).
Jetzt erstellen wir noch die Datei /opt/docker-compose.yml mit folgendem Inhalt:
version: '3.2'
services:
php:
container_name: php
image: my-php:latest
restart: always
volumes:
- type: bind
source: /opt/www
target: /var/www
bind-propagation: rshared
- type: bind
source: /opt/etc/php
target: /usr/local/etc
bind-propagation: rshared
- type: bind
source: /opt/www/cache
target: /etc/nginx/cache
bind-propagation: rshared
- type: bind
source: /opt/www/log/php
target: /var/log/php
bind-propagation: rshared
- type: bind
source: /opt/scripts/client
target: /root/scripts
bind-propagation: rshared
- type: bind
source: /opt/git/etc/aws
target: /root/.aws
bind-propagation: private
nginx:
container_name: nginx
image: my-nginx:latest
ports:
- "80:80"
- "443:443"
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
restart: always
depends_on:
- php
volumes:
- type: bind
source: /opt/www
target: /var/www
bind-propagation: rshared
- type: bind
source: /opt/etc/nginx/conf.d
target: /etc/nginx/conf.d
bind-propagation: rshared
- type: bind
source: /opt/etc/nginx/sites
target: /etc/nginx/sites
bind-propagation: rshared
- type: bind
source: /opt/etc/nginx/cert
target: /etc/nginx/cert
bind-propagation: rshared
- type: bind
source: /opt/etc/nginx/nginx.conf
target: /etc/nginx/nginx.conf
bind-propagation: rshared
- type: bind
source: /opt/www/cache
target: /etc/nginx/cache
bind-propagation: rshared
- type: bind
source: /opt/www/log/nginx
target: /var/log/nginx
bind-propagation: rshared
- type: bind
source: /opt/www/certbot/conf
target: /etc/letsencrypt
bind-propagation: rshared
- type: bind
source: /opt/www/certbot/www
target: /var/www/certbot
bind-propagation: rshared
certbot:
container_name: certbot
image: certbot/certbot
restart: always
depends_on:
- nginx
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
volumes:
- type: bind
source: /opt/www/certbot/conf
target: /etc/letsencrypt
bind-propagation: rshared
- type: bind
source: /opt/www/certbot/www
target: /var/www/certbot
bind-propagation: rshared
- type: bind
source: /opt/www/log/certbot
target: /var/log/letsencrypt
bind-propagation: rshared
Achtung, MySQL wird nicht mitgeliefert, kann aber einfach eingebaut werden.
Das Docker Konstrukt wird mit folgendem Befehl gestartet:
docker-compose -f /opt/docker-compose.yml up --force-recreate -d ; Startet Docker Container docker exec `docker ps -a -f name=certbot -q` /etc/letsencrypt/start.sh ; Let's Encrypt soll Zertifikate requesten docker exec `docker ps -a -f name=nginx -q` nginx -s reload ; Neue Zertifikate im Nginx laden
oder gestoppt:
docker-compose -f /opt/docker-compose.yml down ; Docker beenden docker ps -a | grep Exit | cut -d ' ' -f 1 | xargs sudo docker rm ; Falls Docker nicht sauber beenden, kann man sie damit löschen
Fehlerdateien sind im /opt/log der Container zu finden.




