OCI 에서 제공되는 무료 서버를 이용하여 nginx(x86) – was(arm64) – DB(arm64) 으로 잘 사용하고 있었다.
기존엔 snapd(certbot) 도 arm64에서 정상 동작지 않았고 http3를 구현한 nginx도 베타 였으나 현재는 mainline-quic 으로 되었기 때문에 native-arm64 환경으로 이행을 통해 메모리가 적어서 상대적으로 속도가 느렸던 x86서버를 버리기 위해서 아래와 같은 목표를 구현하는 것을 목표로 잡았다.
1. Docker – rockylinux9 – nginx-quic(http3) 구축
2. Docker – Was(http,php-fpm) 의 OS를 amazonlinux2 -> rockylinux9 으로 변경 하여 php-8.3 사용
베이스 OS는 rockylinux 8(arm64) 이며, 먼저 arm 서버에 docker, memcached 를 설치하고 활성화 한다.
php-fpm에서 세션 저장 위치로 호스트OS에 memcached(:11211)를 사용한다.
1 2 3 |
~]# dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo ~]# dnf -y install docker-ce docker-ce-cli containerd.io docker-compose-plugin memcached ~]# systemctl enable --now docker.service memcached.service |
Was 컨테이너 안에서 웹서비스가 apache:apache 권한 으로 동작 되기 때문에 아래와 같이 베이스 os에 같은 권한을 생성하여 웹동작 과 웹서비스 폴더및 파일의 소유권을 일치화 한다.
1 2 3 4 |
~]# groupadd -g 48 apache ~]# useradd -s /sbin/nologin -u 48 -g apache -d /usr/share/httpd -c Apache apache ~]# mkdir -p /var/www/html ~]# chown -R apache:apache /var/www/html |
파이어월 설정을 해서 memcache 와 was 포트를 허용한다.
1 2 3 |
~]# firewall-cmd --add-service=memcache --permanent ~]# firewall-cmd --add-port=8000/tcp --permanent ~]# firewall-cmd --reload |
https://hub.docker.com/r/san0123/rocky9-arm64-http-php
도커는 pull 을 별도로 하지 않더라도 정확한 주소를 사용할 경우 자동으로 pull 하는 기능이 있으므로 바로 run 을 실행 한다. nginx 가 80,443 을 사용할 예정이기 때문에 9000번 포트를 이용해 run 한다.
1 2 |
~]# docker run -d --name main_site --add-host host.docker.internal:host-gateway --restart always \ -p 9000:80 -v /var/www/html:/var/www/html san0123/rocky9-arm64-http-php:8.3 |
Nginx 용 도커를 띄우기 위해 아래와 같이 방화벽 설정을 한다.
1 2 3 4 |
~]# firewall-cmd --add-service=http --permanent ~]# firewall-cmd --add-service=https --permanent ~]# firewall-cmd --add-port=443/udp --permanent ~]# firewall-cmd --reload |
웹용 도커는 베이스os에서 virtualhost 설정파일을 수정 하고 docker를 재실행 하기 위해 먼저 해당 파일을 생성해 둬야 한다.
1 2 |
~]# mkdir -p /var/www/conf ~]# touch /var/www/conf/virtual.conf |
https://hub.docker.com/r/san0123/rocky9-arm64-nginx
Nginx용 도커를 실행 한다.
컨테이너를 재 생성 할때마다 인증서나 가상호스트 파일을 수정하지 않도록 두개의 마운트 포인트를 추가해서 실행한다.
1 2 3 4 5 |
~]# docker run -d --name nginx_docker \ -p 80:80 -p 443:443 -p 443:443/udp \ -v /etc/letsencrypt:/etc/letsencrypt \ -v /var/www/conf/virtual.conf:/etc/nginx/conf.d/virtual.conf \ san0123/rocky9-arm64-nginx |
Let‘s encrypt 를 생성하는 명령어는 다음과 같다.
1 2 3 |
~]# docker exec nginx_docker /usr/local/bin/certbot certonly --server https://acme-v02.api.letsencrypt.org/directory --rsa-key-size 4096 --agree-tos --email 이메일@주소.com --webroot -w /var/www/html \ -d www.도메인.com -d 도메인.com -d grafana.도메인.com |
이후 베이스OS 에서 /var/www/conf/virtual.conf 를 자신의 url에 맞게 수정하고 발급된 인증서가 동작할 수 있도록 아래와 같이 수정을 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
### http server server { listen 80; server_name www.도메인.com 도메인.com grafana.도메인.com; include security_params; include security_method_params; location ^~ /.well-known/acme-challenge/ { root /var/www/html/; } location / { rewrite ^ https://$host$request_uri? permanent; } } ### http2 set for example.com -> www.example.com ### server { listen 443 ssl; server_name 도메인.com; location / { return 301 https://www.$server_name$request_uri; } ssl_certificate /etc/letsencrypt/live/www.도메인.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.도메인.com/privkey.pem; add_header Strict-Transport-Security 'max-age=31536000; preload'; include http2_params; } ### http3 only one site ### server { listen 443 ssl; listen 443 quic reuseport; server_name www.도메인.com; include security_params; include security_method_params; location / { include proxy_params; proxy_pass http://host.docker.internal:9000; } ssl_certificate /etc/letsencrypt/live/www.도메인.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.도메인.com/privkey.pem; add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload'; include http2_params; include http3_params; } ### http2 other site ### server { listen 443 ssl; server_name grafana.도메인.com; include security_params; if ( $request_method !~ ^(GET|POST|PUT|DELETE|HEAD|OPTIONS)$ ) { return 405; } allow 123.123.123.123/32; deny all; location / { include proxy_params; proxy_pass http://host.docker.internal:3000; } ssl_certificate /etc/letsencrypt/live/www.도메인.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.도메인.com/privkey.pem; add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload'; include http2_params; } |
이후 nginx를 재시작 하기 위해 컨테이너를 재시작 한다.
1 |
~]# docker restart nginx_docker |
http3가 잘 활성화 되어있는지 확인 한다. ( https://http3check.net/ )
인증서가 약 2-3개월 마다 갱신해야 하기 때문에 cronatb에 아래와 같이 등록해서 주기적인 인증서 업데이트 및 적용을 위한 재시작을 한다. (매주 월요일 오전 8시)
1 |
00 08 * * 1 bash docker exec nginx_docker /usr/local/bin/certbot renew && docker restart nginx_docker |