처음으로 Docker를 활용해 토이 프로젝트를 원격 서버에 배포해보았고, 쉽지 않았기에 따로 정리해두려고 한다.
Docker-Compose 방식도 있었는데, 일단 초입부인 만큼 기본적인 것만 다루어보자.
2월 동안 Docker 환경에 대한 기본적인 적응 및 CI/CD를 적용해보는 것이 내 목표이다.
Dockerhub 아이디가 없으면 새로 만들어야 한다.
위와 같이 Dockerhub 개인 화면에 접속했다면, 닉네임 및 비밀번호를 기억해두어야 한다.
이제 배포하려는 프로젝트의 루트 파일에 Dockerfile를 작성해야 한다.
# 기본 이미지는 jdk 17
FROM openjdk:17
#빌드 시점에 사용될 변수를 정의
#JAR_FILE은 빌드 컨텍스트 내의 jar 파일 경로를 지정하는 데 사용
ARG JAR_FILE=build/libs/*.jar
# ARG에서 정의한 JAR_FILE 경로의 jar 파일을 컨테이너 내 app.jar로 복사
COPY ${JAR_FILE} app.jar
# 컨테이너가 시작될 때 실행될 명령어 정의
ENTRYPOINT ["java","-Dspring.profiles.active=docker", "-jar","app.jar"]
Dockerfile을 다 작성했다면, Springboot 프로젝트의 Terminal을 켜고 아래와 같은 명령어를 입력한다.
./gradlew clean build -x test
Springboot 프로젝트를 Gradle 기반으로 빌드한다. 단 테스트 코드는 배제한다.
docker login
dockerhub에 username 및 password로 로그인한다.
docker build --platform linux/amd64 -t [사용자ID]/[파일명] .
docker 파일을 특정 파일명으로 빌드하되, 플랫폼은 linux/amd64이다.
참고로 M1에서 EC2 Ubuntu x86로 Docker 프로젝트를 배포할 경우 반드시 플랫폼 관련 명령어가 존재해야 한다. 그렇지 않으면 에러가 발생한다.
docker push [사용자ID]/[파일명]
빌드한 Dockerfile을 Dockerhub에 Push한다.
spring.datasource.url=jdbc:postgresql://[Docker host IP주소]:5432/[DB명]
spring.datasource.username=postgres
spring.datasource.password=[비밀번호]
spring.datasource.driver-class-name=org.postgresql.Driver
# JPA
spring.jpa.hibernate.ddl-auto=create # 기존에 존재하던 데이터가 있다면 create X
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.database=postgresql
우리는 EC2 Docker에 진입하여 Docker를 활성화한 후 PostgreSQL에게 할당되는 IP Address를 알아야 한다.
기본적인 상황이라 username이 postgres지만, 필요에 따라 다양한 권한을 가진 DB 유저를 구축해야 할 수도 있다.
Dockerfile이 성공적으로 빌드 및 Push되었다면 EC2 Ubuntu로 이동한다.
ssh -i [키 페어 파일명] ubuntu@[할당받은 탄력적 IP]
EC2 인스턴스 생성 시 내려받은 키페어 파일명 및 탄력적 IP를 활용해
원격 컴퓨터에 접속한다. 인바운드 설정 등은 생략한다. (8080 포트)
sudo apt update
sudo apt install docker.io
원격 컴퓨터 Ubuntu를 업데이트하고 docker를 설치한다.
docker run --name [postgresql 컨테이너명] \
-p 5432:5432 \
-e TZ=Asia/Seoul \
-e POSTGRES_PASSWORD=[비밀번호] \
-d postgres
postgreSQL 이미지를 설정대로 다운로드받은 후 컨테이너화한다.
비밀번호는 application.properties(yaml)에 존재하는 spring.datasource.password과 동일해야 한다.
postgreSQL 컨테이너화가 성공했다면 추가적인 정보를 얻어야 한다.
나는 ddl-auto create이기 때문에 postgreSQL 컨테이너에 진입하여 데이터베이스를 새로 생성해주었다.
docker exec -it [컨테이너 ID] bash
psql -U postgres
exec 명령어로 외부에서 컨테이너로 진입하고, 위에서 설정한 비밀번호를 입력한 뒤 create database [데이터베이스명]으로 DB를 새로 생성한다.
postgreSQL 컨테이너에게 할당된 Docker Host IP주소를 확보하자.
docker inspect [postgresql 컨테이너명] | grep IPAddress
inspect 명령어를 통해 컨테이너의 상세 정보 중 컨테이너에게 도커가 할당해준 Host IP주소를 확인하고, 해당 값을 application.properties(yaml)의 spring.datasource.url에 채워넣는다.
docker run -d --name [Springboot 컨테이너명] -p 8080:8080 [사용자ID]/[파일명]
Docker Repository에서 Docker Image를 pull하여 내려받고 이를 통해 Springboot 프로젝트를 실행(컨테이너화)한다.
-d를 통해 백그라운드에서 실행하게 하여 터미널이 다른 작업을 수행할 수 있게 하고,
--name을 통해 자체적인 별명을 부여한다.
-p를 통해 포트를 부여한다. (8080)
참고로 최초 run을 실행했다면 그 다음부터는 run이 아니라 <docker start [컨테이너명]> 으로 컨테이너를 실행해야 한다. 그렇지 않으면 Docker 내부에 같은 내용을 담은 컨테이너가 창궐(?)하게 된다.
다음은 관련 작업 시 필요한 기본적인 Docker 명령어이다.
여기를 참고하여 작성하였다.
docker attach [컨테이너명]
컨테이너 실행 시 사용한다. (직접 컨테이너 내부를 실시간으로 들여다본다.)
Ctrl + P + Q로 쉘을 빠져나올 수 있다.
docker start(stop) [컨테이너명]
컨테이너를 실행하거나, 실행되던 컨테이너를 중단시킨다.
docker logs [컨테이너명]
해당 컨테이너가 생성하는 로그를 조회할 수 있다.
docker ps (-a)
현재 실행중인 컨테이너의 목록을 조회할 수 있다.
-a를 통해 모든 컨테이너를 조회할 수도 있다.
docker rmi [이미지id]
pull이나 run으로 내려받은 docker 이미지를 삭제한다.
docker rm -f [컨테이너id]
해당 docker 컨테이너를 (강제로) 삭제한다.
참고로, Got permission denied while trying to connect to the Docker daemon~으로 시작하는 에러는 아래와 같이 해결했다.
sudo chmod 666 /var/run/docker.sock
sudo usermod -aG docker ${USER}
다음에는 CI/CD도 도전해볼 계획이다.
여담으로, 에러가 정말 많이 나서(특히 postgreSQL 연동 관련) 굉장히 당혹스러웠다.