IT/Docker

[Docker] apache-php 컨테이너에서 https 연결하기 feat.Let's Encrypt

월공 2023. 4. 7. 23:13
728x90
300x250

환경 : 호스트 Centos 7 , Docker 컨테이너 (apache-php) , let's encrypt (SSL)

let's encrypt 설치는 이미 잘 정리되어있는 블로그 글들이 많아서 굳이 기재하지 않겠습니다.
제가 포스팅했던 적도 있어서 링크만 걸어놓을게요
제목은 centos8 이라 되있지만 7에서도 잘됩니다.

https://bug41.tistory.com/entry/SSL-Lets-Encrypt-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EC%84%A4%EC%B9%98-Centos8-crontab

 

[SSL] Let's Encrypt SSL 인증서 설치 Centos8 , crontab

센토스8 에서 홈페이지 https 를 위한 Let's Encrypt 설치 방법 간단하게 포스팅합니다. Let's Encrypt 설치 sudo dnf install epel-release 혹시 아래처럼 오류 뜨면서 안되면 Failed to set locale, defaulting to C.UTF-8 CentO

bug41.tistory.com


let's encrypt 가 잘 설치 되었다는 가정하에 진행합니다.

# 내가 원하는 도메인에 let's encrypt 발급, www 붙은거랑 안붙은거 동시에 발급
certbot --apache -d baam82.kr -d www.baam82.kr

정상적으로 진행이 되었다면 아래처럼 비스무리하게 보일겁니다.

[root@tw-web ipsets]# certbot --apache -d baam82.kr -d www.baam82.kr
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator apache, Installer apache
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
You have an existing certificate that contains a portion of the domains you
requested (ref: /etc/letsencrypt/renewal/baam82.kr.conf)

It contains these names: baam82.kr

You requested these names for the new certificate: baam82.kr, www.baam82.kr.

Do you want to expand and replace this existing certificate with the new
certificate?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(E)xpand/(C)ancel: E
Renewing an existing certificate for baam82.kr and www.baam82.kr
Performing the following challenges:
http-01 challenge for baam82.kr
http-01 challenge for www.baam82.kr
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/httpd/conf/httpd-le-ssl.conf
Deploying Certificate to VirtualHost /etc/httpd/conf/httpd-le-ssl.conf
Redirecting vhost in /etc/httpd/conf/httpd.conf to ssl vhost in /etc/httpd/conf/httpd-le-ssl.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Your existing certificate has been successfully renewed, and the new certificate
has been installed.

The new certificate covers the following domains: https://baam82.kr and
https://www.baam82.kr
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/baam82.kr/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/baam82.kr/privkey.pem
   Your certificate will expire on 2023-07-02. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again with the "certonly" option. To non-interactively
   renew *all* of your certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/baam82.kr/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/baam82.kr/privkey.pem

일단 다른거 다 필요없고 정상적으로 발급되었다고 하면 맨 하단에 내 인증서 깔린 경로가 중요합니다.
왜냐면 저 부분을 도커 컨테이너 생성할때 마운트 시켜줄거거든요

 

이제 아래처럼 apache-php 이미지를 이용하여 도커 컨테이너를 생성해줄건데 명령어가 복잡해보이지만 굳이 필요하지않은게 몇개 있어서 --restart="always" 라던가 --privileged 는 굳이 필요없을거에요
차례대로 살펴보자면

docker run --restart="always" -itd --privileged -p 80:80 -p 443:443 --network mynet \
-v /var/www/html/baam82:/var/www/html \
-v /etc/letsencrypt/archive/baam82.kr:/etc/ssl \
 --name baam82 php:7.4-apache

-p 80:80 응 호스트 80으로 들어오는거 도커 80으로 보낼게~
-p 443:443 응 호스트 443 으로 들어오면 도커 443 으로 보낼게 ~

--network mynet 이것도 굳이 필요없으실건데 제 경우엔 mariaDB 컨테이너가 별도로 운영중이어서 이놈을 고정 IP 로 쓰려고 docker network 를 하나 만들어놓은게 있어서 컨테이너끼리 연결 편하게 하려고 같은 network 로 잡아서 생성을 했습니다.

-v [호스트경로]:[도커 경로]

/var/www/html 경로 마운트 잡는건 그렇다쳐도 letsencrypt 경로 부분에서 좀 의아하실건데 분명히 위에서 제가 언급한
중요하다고 언급했던 경로는 아래와 같습니다.
/etc/letsencrypt/live/baam82.kr/fullchain.pem
/etc/letsencrypt/live/baam82.kr/privkey.pem

근데 정작 컨테이너 실행시킬때는 "/etc/letsencrypt/archive" 로 마운트를 걸었습니다.

이 부분은 처음에 제가 삽질을 좀 했던 부분인데 호스트 서버에서 
vi /etc/letsencrypt/live/baam82.kr/fullchain.pem 요런식으로 열면 잘 열리고, 근데 정작 만들었던 컨테이너에서 vi 를 때리면 못찾아갑니다
그래서 자세히 살펴보니 심볼릭링크로 ../../archive 에 있는걸 갖고가길래 archive 에 있는 원본쪽으로 마운트 시켜주니
잘 찾아갔습니다.

#테스트 한답시고 여러번 재발급받아서 뒤에 2가 붙은듯합니다. 별로 중요한건 아님
lrwxrwxrwx 1 root root  33 Apr  3 21:51 cert.pem -> ../../archive/baam82.kr/cert2.pem
lrwxrwxrwx 1 root root  34 Apr  3 21:51 chain.pem -> ../../archive/baam82.kr/chain2.pem
lrwxrwxrwx 1 root root  38 Apr  3 21:51 fullchain.pem -> ../../archive/baam82.kr/fullchain2.pem
lrwxrwxrwx 1 root root  36 Apr  3 21:51 privkey.pem -> ../../archive/baam82.kr/privkey2.pem


여튼 저대로 컨테이너가 정상적으로 만들어졌다면

docker ps -a

아래처럼 보일겁니다.

이제 아래 명령어로 도커 컨테이너에 접속해서 몇가지 조정을 해줍니다.

# docker 컨테이너 접속
docker exec -it baam82 /bin/bash

# 이것저것 세팅에 필요한거 설치
# apache.conf 수정할때 vim 필요
# db 연결 안하시면 docker-php-ext-install mysqli 는 굳이 필요없음

apt-get update && apt-get install -y vim && docker-php-ext-install mysqli

/var/www/html 마운트 정상

/etc/ssl 마운트 정상



해당 apache-php 의 아파치 설정 config 파일은 경로가 아래와 같습니다.

#httpd.conf 인줄 알았으나 아님
vi /etc/apache2/apache2.conf

#VirtualHost 세팅은 아래에서 
vi /etc/apache2/sites-available/000-default.conf


apache2.conf 에서는 별다른 수정사항은 없었습니다
그냥 serverName 추가



핵심은 000-default.conf (보통 사이트이름.conf 로 하는듯, 대신 apache2.conf 에서 정상적으로 포함되게 해줘야겠죠) 

<VirtualHost *:80>
    ServerName www.baam82.kr
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
    Redirect "/" "https://baam82.kr/"
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

<VirtualHost *:443>
    ServerName baam82.kr
    SSLEngine On
    SSLCertificateFile /etc/ssl/fullchain2.pem
    SSLCertificateKeyFile /etc/ssl/privkey2.pem    
</VirtualHost>

이렇게 다 수정하고 아래 명령어로 아파치 서버 재시작이 가능합니다.

#아파치 서버 재시작
apachectl restart

#아파치 서버 재시작
service apache2 restart

아래 처럼 정상적으로 http 로 접속을해도 apache2.conf 에서 Redirect 로 설정해준 덕분에 https 로 바로 보내줘서 잘열리는것이 확인 되었습니다.

 


사실 정리하고나니 별거 아닌데 여기까지 오기까지 시행착오를 좀 겪었습니다.

1. 호스트 서버에도 apache 가 필요할줄알았는데 전혀 아니었음, 도커 아파치 컨테이너만으로도 충분히 가능

2. apache 컨테이너 랑 php 컨테이너 별도로 진행 하고 같은 network 에 올려서 ProxyPassMatch 어쩌고 작업을 하려했는데 여러번 삽질하다 실패 , 그냥 apache 컨테이너에 php 깔아서 진행하거나 , php:7.4-apache 공식 이미지 사용하는게 정신건강에 이로움

3. certbot 실행했을때 방화벽 때문에 정상적으로 인증서 발급이 되지않는 문제도 있었고 알고보니 예전에 해외 ip 접근 차단한 rich-rules 때문에 그랬음. ( /etc/firewalld/ipset  안에 있음 )
방화벽 잠깐 내리고 재발급 완료

4. SSL 모듈 안깔려있어서 오류 발생 아래 명령어로 SSL 확인 및 설치 가능

# SSL 모듈 깔려있는지 확인
apachectl -M | grep ssl

# SSL 모듈 안깔려있으면 설치 명령어
a2enmod ssl

 

사실 위에서 진행한 apache-php 컨테이너에 접근해서 이것저것 명령어 칠 필요없이 docker-compose 를 이용해서 한번에 끝낼수 있을듯합니다.
그리고 let's encrypt 는 3개월마다 갱신을 해줘야하니 crontab 을 이용해서 자동갱신을 해줘야겠지요 ~!

728x90
300x250