[Docker] Docker Container와 Nginx를 활용한 HTTPS 적용기

2025. 3. 3. 20:46
728x90

아주 다양한 오류들을 마주쳤다... = 내가 성장하는 과정

잊지 않도록 기록하기

 

 

나의 현재 상황은 
Nginx로 SSL 인증서는 받았고, 도커 이미지로 업로드하다가 HTTPS 적용이 어려워서 결국 Docker Container로 Nginx 서버와 Backend 서버를 함께 올리기로 함. 
그리고 이를 위해 github에 올리고, 해당 소스를 EC2 인스턴스에서 받아 docker compose up 하기로 함.


1. 첫번째 오류

깃에서 pull 받고 빌드 해보는 과정에서 이러한 오류가 났다. 

RefrigBackendApplicationTests > contextLoads() FAILED
    java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:180
        Caused by: org.springframework.beans.factory.BeanCreationException at AbstractBeanFactory.java:325
            Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException at ConstructorResolver.java:804
                Caused by: org.springframework.beans.factory.BeanCreationException at ConstructorResolver.java:657
                    Caused by: org.springframework.beans.BeanInstantiationException at SimpleInstantiationStrategy.java:199
                        Caused by: org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException at DataSourceProperties.java:186

* What went wrong:
Execution failed for task ':test'.
> There were failing tests. See the report at: file:///home/ec2-user/refrig-backend/build/reports/tests/test/index.html

테스트 과정에서 오류가 났는데, 데이터소스를 찾지 못하는 문제였다. 

 

이건 아주 간단한 바보같은 문제였다. 

 

<문제점/해결책>

git에 보안상 문제로 yml 파일을 올리지 않았고, 그러므로 EC2에서는 yml 파일이 없이 실행되어 데이터베이스를 찾을 수 없었던 것.

완전 기본이자너~~~~

그래서 yml 파일을 gitignore에서 빼고, 보안에 문제되는 부분을 환경변수로 마스킹 처리를 했다. 

그리고 해당 민감정보를 EC2에서 환경변수로 설정하였다. 

나는 ~/.bashrc 내부 내용을 바꿔주었다.

export JAVA_HOME=/usr/lib/jvm/java-17-amazon-corretto.x86_64
export PATH=$JAVA_HOME/bin:$PATH
export DB_URL=jdbc:mysql://refrig-db.xxxx.ap-northeast-2.rds.amazonaws.com:3306/refrig
export DB_USERNAME=root
export DB_PASSWORD=password

요렇게 해두고 꼭 echo를 통해 확인해보시길 바란다. 

나는 계속 적용이 안돼서 빌드오류 여러번 겪음.

또한, 적용이 안될때 인스턴스 재접속 및 source ~/.bashrc 명령어로 재적용하기 ~!!!

결국 빌드 성공!

 

** 여담으로 github에서 environment로 설정하면 되지 않을까? 했는데, 그거는 Github Actions 파이프라인을 사용해야만 가능하다고 한다. 현재 아직 CI/CD 적용을 하지 않았기 때문에 임시로라도 직접 환경변수를 입력해주게 되었다. 

 

 

2. 두번째 오류 

이후 도커 컴포즈 올렸을 때 database 연결에서 문제가 생겼다.

refrig  | 2025-03-03T09:32:49.886Z ERROR 1 --- [refrig] [           main] o.s.boot.SpringApplication               : Application run failed
refrig  | org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is java.lang.RuntimeException: Driver com.mysql.cj.jdbc.Driver claims to not accept jdbcUrl, ${DB_URL}
refrig  | at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1812) ~[spring-beans-6.2.2.jar!/:6.2.2]
...
dependency failed to start: container refrig exited (1)

이제 되야 하는데, 왜 또 디비 문제가 나타난 것이냐~~~~~

Driver com.mysql.cj.jdbc.Driver claims to not accept jdbcUrl, ${DB_URL}

 

 

 

<문제점/해결책>

이번에는 application.yml 파일에서는 적용이 되어 빌드는 되지만,,, 스프링 부트 실행 시 ${DB_URL}이라는 문자열을 그대로 받아, 도커 컨테이너 내부에는 해당 환경변수가 전달되지 않았다. 

 

** 왜 컨테이너에서 환경 변수를 못 읽을까!?

>> 도커 컨테이너는 호스트 OS의 환경변수와 격리되어 있다. 그래서 도커 내부에서 echo $DB_URL 해보아도 나오지 않는다. 

 

 

>> docker-compose.yml에서 환경 변수를 넘겨주어야 한다! (도커 컴포즈로 컨테이너를 띄울 때 필요한 환경 변수를 컨테이너로 전달해주어야 한다.)

이렇게 docker-compose.yml을 수정해주었다. 

환경 변수는 EC2에 설정되어 있는 상태이고, docker-compose에서 환경변수를 참조하는 식으로 설정해주었다. 

 

그랬더니 스프링부트는 정상적으로 시작됨!!

 

 

3. 세번째 오류

도커 컴포즈 올렸더니 nginx에서 또 문제가 있는 것 같다.

failed to create shim task
error mounting "...privkey.pem" to rootfsat ".../privkey.pem"
...
not a directory: unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type

 

<문제점/해결책>

오류 메시지를 보면 마운트 하는 데에서 오류가 생겼다. 호스트의 어떤 경로를 도커 컨테이너 안의 경로와 부적절하게 매핑되어 발생하는 문제이다. 

 

원래의 docker-compose.yml 파일을 보면 이렇게 경로설정을 해두었다. 

docker-compose.yml

 

도커 볼륨 마운트 시 1) 호스트 쪽 경로가 디렉터리인지, 2) 컨테이너 쪽 경로가 디렉터리인지 확인을 해야 한다.

내가 설정한 경로는 호스트 쪽은 디렉터리였고,,, 컨테이너 쪽 경로는 파일이었다. 

그래서 이렇게 변경 해주었다. 

폴더 대 폴더로 마운트 변경.

 

 

 

그러나 여전히 오류가 났다. 스프링은 정상적으로 올라갔고, nginx측에서 문제가 생김.

cannot load certificate
PEM_read_bio_X509_AUX() failed (SSL: error:0480006C:PEM routines::no start line:Expecting: TRUSTED CERTIFICATE)

흠 이건 또 모야~했는데 호스트 쪽 디렉터리를 확인해보았더니 

호스트 쪽 디렉터리에 인증서가 존재한다고 생각했는데, 아니었다. 디렉터리 안이 비어있어서 파일이 존재하지 않는 상황이었다. 

그래서 실제 인증서가 존재하는 디렉터리로 설정!!!

+ 또한, 중요한 것은 인증서가 존재하는 letsencrypt/live/ 디렉터리는 심볼릭 링크 구조로, 사실은 archive 디렉터리를 따라가게 된다. 

오류
archive까지 포함한 경로로 설정해주어야 함.

 

그래서 심볼릭 링크의 실제 대상 경로도 컨테이너 내부에서 유효해야 한다. live 디렉터리 내부로만 설정하면 archive로 링크가 연결될 수 없다. 

 

 

 

>> 짜잔 결과는 

드디어 nginx도 같이 올라갔고, https가 완벽히 적용된 테스트 화면을 볼 수 있게 되었다.

 

 

 

 

 

흑 이 배포 문제를 몇일간을 매달리며... 좌절의 순간들을 겪었지만, 

영원히 안되라는 법은 없다...!!!

앞으로 조금씩 나아가는 과정이기를  

728x90

BELATED ARTICLES

more