OCI 에서 제공되는 무료 서버를 이용하여 nginx(x86) – was(arm64) – DB(arm64) 으로 잘 사용하고 있었다. (물론 앞으로도 잘 사용할 예정…)
기존엔 snapd(certbot) 도 arm64에서 정상 동작지 않았고 http3를 구현한 nginx도 베타 였으나 현재는 mainline-quic 으로 되었기 때문에
native-arm64 환경으로 이행을 통해 메모리가 적어서 상대적으로 속도가 느렸던 x86서버를 버리기 위해서 아래와 같은 목표를 구현하는 것을 목표로 잡았다.
1. Docker – Was(http,php-fpm) 의 OS를 amazonlinux2 -> rockylinux9 으로 변경 하여 php-8.3 사용
2. Docker – rockylinux9 – nginx-quic(http3) 구축
3. Docker x86_64(amd64), arm64(aarch64) 을 지원
베이스 OS는 rockylinux 9 (aarch64)이며, 서버에 docker 를 설치하고 활성화 한다. (Install Docker Desktop on RHEL)
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 ~]# systemctl enable --now docker.service |
Was 컨테이너 안에서 웹서비스가 apache:apache 권한 으로 동작 되기 때문에 아래와 같이 베이스 os에 같은 유져를 생성하게 되면 퍼미션 지정이 불필요 하다. (바깥에서 단순 UID 48으로 지정해 운영 해도 된다.)
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 |
도커는 pull 을 별도로 하지 않더라도 정확한 주소를 사용할 경우 자동으로 pull 하는 기능이 있으므로 바로 run 을 실행 한다. nginx 가 80,443 을 사용할 예정이기 때문에 9000번 포트를 이용해 run 한다. (https://hub.docker.com/r/san0123/rocky9-http-php)
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-http-php:8.3 |
웹소스를 호스트os의 /var/www/html에 넣으면 호출을 할수 있다.
파일을 복사하거나 압축을 해제한 후에는 chown -R apache:apache 파일명
을 잊지 말자…
Nginx 도커를 이용한 http2를 위해 80/tcp, 443/tcp 그리고 http3를 위해 443/udp 을 파이어월에서 허용 한다.
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 설정 파일 을 저장해서 버전 업데이트시 설정 파일을 새로 설정 하지 않기 위해 mount 하기 때문에 먼저 생성을 한뒤 docker run 을 해야 한다.
1 2 |
~]# mkdir -p /var/www/conf ~]# touch /var/www/conf/virtual.conf |
Nginx용 도커를 실행 한다. 컨테이너를 재 생성 할때마다 인증서나 가상호스트 파일을 수정하지 않도록 두개의 마운트 포인트를 추가해서 실행한다. (https://hub.docker.com/r/san0123/rocky9-nginx)
1 2 3 4 5 |
~]# docker run -d --name nginx_docker \ -p 80:80 -p 443:443 -p 443:443/udp --add-host host.docker.internal:host-gateway \ -v /etc/letsencrypt:/etc/letsencrypt \ -v /var/www/conf/virtual.conf:/etc/nginx/conf.d/virtual.conf \ san0123/rocky9-nginx |
--add-host host.docker.internal:host-gateway
옵션은 베이스OS 에서 제공 중인 다른 서비스 포트에 접근하기 위한 설정이기 때문에 필요에 따라 제거 할 수 있다.
도메인을 서버에 연결 한 뒤에 Let‘s encrypt 를 생성하는 명령어는 다음과 같다. (email, webroot, domain 은 자신에 맞게 수정해서 사용한다.)
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 56 57 58 59 60 61 62 |
### 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; include http2_params; 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'; location / { return 301 https://www.$server_name$request_uri; } } ### http3 only one site ### server { listen 443 ssl; listen 443 quic reuseport; server_name www.도메인.com; include security_params; include security_method_params; include http2_params; include http3_params; 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'; location / { include proxy_params; proxy_pass http://host.docker.internal:9000; } } ### http2 other site ### server { listen 443 ssl; server_name grafana.도메인.com; include security_params; include http2_params; 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'; if ( $request_method !~ ^(GET|POST|PUT|DELETE|HEAD|OPTIONS)$ ) { return 405; } allow 123.123.123.123/32; deny all; location /api/live/ { proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass http://host.docker.internal:3000; } location / { include proxy_params; proxy_pass http://host.docker.internal:3000; } } |
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 |
데이터베이스 사용법 까지 필요 하면 아래 포스트를 확인 하자 ‘ㅅ’a