DevOps

서버에 docker 컨테이너로 배포하기

soohey 2023. 3. 15. 14:30

안녕~

오늘은 도커로 서버에 배포하는 걸 정리해볼 예정이다.

순서는

 

1. Dockerfile 생성후 이미지 빌드하기

2. 생성된 이미지로 컨테이너 구동하기

 

위 정도의 순서로 간단히 실습해보자.

 

1. 도커 파일 만들기

도커는 Dockerfile에서 조건들을 읽어서 이미지를 자동으로 빌드한다.

즉 Dockerfile이 있어야만 이미지를 빌드할 수 있다.

 

Dockerfile은 다양한 종류의 커맨드로 작성이 되어 있어서 조건 같은 것들을 달 수도 있고,

이미 공식 Docker Hub에 올라간 이미지를 가져올 수도 있다. 

Docker Hub는 이미지를 올릴 수 있는 저장소 같은거라고 생각하면 된다.

나중에 배포 자동화를 할 경우 로컬에서 Docker Hub에 이미지를 push하고 서버에서 pull하도록 젠킨스를 이용하여 운영할 수 있다.

 

Dockerfile은 무조건 from이라는 명령어로 시작해야한다.

나는 스프링 프로젝트를 jar파일로 만든 후 구동시키는 Dcokerfile을 작성할 것이다.

FROM openjdk:11

ARG JAR_FILE=*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

// ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod","/app.jar"]
// => 설정파일을 분리해서 사용할 때
// java -jar -Dspring.profiles.active=prod app.jar

ADD src dest
ADD hom* /mydir/

FROM은 기반이 되는 이미지를 이야기한다. 

spring boot 프로젝트의 경우 당연히 JDK 설치가 필요하므로 위처럼 jdk를 가져와야한다.

나는 11버전이라 저렇게 했고, 다른 버전일 경우 숫자만 바꿔서 하면 된다. (에러나면 Docker hub 들어가서 검색해서 아무거나 이름 따오면 됨)

 

ARG는 컨테이너 내에 사용할 변수를 설정할 수 있다.

위 코드에서는 JAR_FILE이라는 변수에 ~.jar 파일 이름을 명시해주었다.

이렇게 설정한 변수는 이미지를 빌드할때 다른 값으로 지정도 해줄 수 있다. ( --build-arg JAR_FILE = 123.jar )

 

COPY는 왼쪽에 있는 값을 오른쪽으로 복사한다는 뜻이다.

오른쪽은 컨테이너의 위치값이므로 로컬 값을 컨테이너 내부로 옮길 수 있다.

위 코드에서는 jar_file을 컨테이너 내부 홈에 app.jar이라는 이름으로 카피했다는 의미다.

 

ENTRYPOINT는 컨테이너 시작시 실행할 스크립트를 명시한다.

spring boot 프로젝트 구동시 java -jar /app.jar 이라는 명령어를 실행시키는데

ENTRYPOINT 사용시 위처럼 [] 대괄호안에 분리해서 써주면 마지막에 실행한다는 뜻이 된다.

그리고 만약 dev, prod 처럼 환경이 달리할 경우 주석에 달린것 처럼 -Dspring.profiles.active=prod로 프로필을 명시해줄 수 있다. 그냥 intellij에서 커맨드로 구동할때처럼 명시해주면 됨.

 

ADD는 왼쪽 값을 오른쪽 경로에 추가한다.

" ADD home /mydir/ " 의 경우 home 값을 컨테이너 내부의 /mydir/에 추가한다는 의미이다.

 

WORKDIR 이라는 명령어는 컨테이너 내부의 작업을 진행할 경로를 지정할 수 있다.

지정하고 나면 이미지에 작성된 모든 명령어는 WORKDIR로 지정된 경로에서 작업이 됨

 

예를 들어

WORKDIR /home 

ADD home /mydir/의 경우 컨테이너 내부 경로는 무조건 /home/mydir로 고정이 된다.

 

그 외에도 docker run할 사용자를 명시하는 USER, STOPSIGNAL, HEALTHCHECK등의 명령어가 있는데 도커 홈에 가면 확인할 수 있다.

 

2. 도커 컨테이너 명령어

이미지 빌드하기

위처럼 도커파일을 작성했다면 이미지를 빌드할 차례이다.

빌드하기전에!! dockerfile은 무조건 jar파일이 있는 곳에서 작성해주자. jar파일 실행해야하는데 jar파일도 없는데 이미지가 빌드될리가 없다.

 

아래처럼 명령어를 친 후 레포 이름을 정한 뒤 빌드해준다. 명령어 마지막에 있는 . 는 도커 파일이 있는 경로를 의미하므로 도커 파일이 있는 장소에서 .를 사용해야 이미지가 제대로 빌드된다.

docker build -t [도커허브ID/레포지토리 이름] .

 

이미지 확인하기

docker images

이미지가 제대로 빌드됐는지 확인하자.

위 명령어를 사용하면 빌드된 이미지 목록을 확인할 수 있다.

 

도커 이미지 허브에 푸시하기

도커 이미지는 hub에 등록한뒤 나중에 pull받아 사용할 수 있다.

hub에 등록하면 어떤 서버에서도 나중에 pull받아 언제든지 작성된 이미지로 배포가 가능하다. 

즉 깃허브 레포랑 비슷한 느낌이라고 생각하면 된다. jar 파일과 이미지만 있으면 어떤 서버에서도 동일한 환경으로 배포가 가능하다!

docker push [도커 허브 ID/레포지토리명]

 

도커 컨테이너 구동하기

드디어 만들어진 이미지로 도커 컨테이너를 띄워보자. 

도커 컨테이너는 이미지로 구동시킬 수 있으며, 하나의 이미지로 여러개의 컨테이너를 구동시킬 수도 있다.

이렇게 할 경우 같은 이미지 (설정파일)로 동일한 환경의 서버를 여러개 띄울 수 있으니 아주아주 편하다.

docker run -p 8080:8080 [도커 허브 ID/이미지 이름]
docker run --name spring-cloud-server -d -p 8010:8080 --restart=always spring-cloud-login

--name 뒤에 띄울 컨테이너의 이름을 지정해준다.

-d는 해당 컨테이너를 백그라운드로 실행한다는 의미이다. 해당 옵션을 지우고 컨테이너 구동시 스프링 부트 실행하는 것 처럼 계속해서 로그를 보여주고, 컨트롤 C를 누르면 강제 종료되는데, 해당 옵션 사용시 로그가 보이지 않아도 계속 실행되고 있다.

-p로 {호스트할 포트 : 컨테이너 포트}를 지정해 포트를 포워딩해준다. 위 코드처럼 작성시 프로젝트 내부의 8080 포트로 접속하면 자동으로 8010으로 접속된다.

--restart=always는 항상 컨테이너를 구동시켜두겠다는 의미이다. 

마지막에는 사용할 도커 이미지 이름을 써주면 된다.

컨테이너 목록 확인하기

docker ps

위 명령어로 컨테이너들의 목록을 확인하고 상태도 볼 수 있다.

STATUS에 UP이라고 되어있으면 정상 작동했다는 뜻이고 COMMAND에 있는게 제일 마지막으로 실행한 도커파일 커맨드라는 뜻이다. 컨테이너는 CONTAINER ID와 NAME으로 구분할 수 있다.

가상 터미널 열기

도커 컨테이너 내부로 접속할 수도 있다. 

docker exec -it  {컨테이너 이름} /bin/bash

위 명령어를 치면 컨테이너 내부에 접속이 되고, 보통 리눅스 환경처럼 이동하거나 파일을 조회할 수 있다.

도커 컨테이너 재실행

docker restart <컨테이너 이름>

도커 컨테이너 삭제하기

docker container stop test-server
docker rm test-server

컨테이너를 삭제하려면 컨테이너를 중단시킨 후 삭제해야한다.