본문 바로가기

Docker

Docker, Dockerfile을 이용한 환경구성 및 실행

Docker

도커란 컨테이너화를 사용해 응용 프로그램의 배포, 확장 및 관리를 자동화할 수 있는 오픈 소스 플랫폼이다.

코드, 실행 시간, 시스템 도구 및 라이브러리를 포함하여 응용 프로그램을 실행하는데 필요한 모든 것을 가볍고 격리된 환경으로 포함한다.

응용 프로그램과 해당 종속성을 표준화된 단위로 패키징하여 다양한 환경에서 일관되게 배포하고 실행하기 쉽게 만들어준다.

 

컨테이너화란 응용 프로그램을 실행하는데 필요한 모든 것을 포함한 가볍게 격리된 환경을 제공한다.

표준화된 단위로 패키징해 일관되게 배포하고 실행하는 것이 목적이다.

 

사용 목적

빠르고 일관된 애플리케이션 제공

효율적인 배포

확장성

격리된 환경

개발 환경의 일관성

 

VM과 Docker의 차이

VM - 호스트 컴퓨터 위에 가상 운영 체제를 실행하는 것으로 각 운영 체제는 자체 커널을 가지고 독립적으로 작동한다.

VM이 완전히 격리되어 있고 서로 영향을 주지 않는다는 이점이 있다. 하지만 VM은 용량과 성능 측면에서 무겁고 비교적 오버헤드가 많이 발생할 수 있다.

 

Docker -호스트 운영 체제 위에 실행하는 것으로 컨테이너라는 단위로 애플리케이션과 필요한 라이브러리 및 종속성을 패키징 한다.

Docker 컨테이너는 호스트 커널을 공유하므로 가볍고 빠르게 실행될 수 있다.

여러 컨테이너를 실행하는 경우 각 컨테이너는 격리되지만 공유 리소스를 사용하여 높은 효율성을 유지한다.

 

가상화의 목적이 격리와 다양한 운영체제의 실행이라면 VM이 적합하나 애플리케이션의 패키징, 배포, 확장이 목적이라면 도커가 적합하다.

https://docs.docker.com/get-started/overview/#docker-architecture

도커 아키텍져 및 흐름이다.

도커를 이용해 클라이언트 - 서버를 구성하는 아키텍처이다.

 

클라이언트는 도커 명령어를 사용해 컨테이너를 실행, 관리, 모니터링하고 이미지를 빌드하거나 다운로드할 수 있다.

도커 호스트는 도커 컨테이너를 실행하는 데 사용되는 가상머신을 의미한다.

도커 데몬을 실행하여 컨테이너를 생성, 시작, 중지 및 관리의 역할을 한다.

클라이언트의 요청을 받아 컨테이너 생성, 시작, 중지, 제거하는 등의 작업을 수행한다. 호스트 운영체제의 리소스를 사용해 컨네이너를 실행하고 관리한다.

도커 레지스트리 도커 이미지를 저장하고 관리하는 중앙 집중식 저장소이다. 도커 허브를 통해 도커 이미지를 공유하고 검색할 수 있게 해 준다.

 

client -> docker host -> registry

docker host -> client

 

client -> docker host 

클라이언트는 도커 명령어를 사용해 도커 호스트에 요청을 보낸다.

docker host

도커 호스트는 클라이언트의 요청을 받고 해당 요청에 따라 컨테이너를 생성, 중지, 제거하거나 이미지를 관리한다.

docker host -> registry

만약 클라이언트가 이미지를 생성하거나 업로드하려면 도커 호스트는 해당 이미지를 도커 레지스트리에 업로드한다.

registry

도커 레지스트리는 이미지를 저장하고 관리하는 중앙 집중식 저장소로 도커 호스트에서는 도커 레지스트리에 이미지를 업로드라거나 다운로드할 수 있다.

docker host -> client

컨테이너가 종료되면 도커 호스트는 해당 컨테이너의 상태와 결과를 클라이언트에 반환한다. 

 

client의 명령어

docker run - 도커 컨테이너를 실행한다.

docker bulid - 도커 이미지를 빌드한다.

docker pull - 이미지를 다운로드해 로컬 도커 환경에 저장한다.

 

도커 주요 용어 요약

 

docker client 도커 클라이언트

도커 컨테이너와 상호작용을 하기 위한 커멘드 라인 도구이다.

명령어들은 많지만 요약식으로 알아보자

docker -v: docker 버전 확인

docker pa -a: docker의 컨테이너 목록을 확인

docker pull [docker image]: docker의 이미지를 다운로드한다.

docker build: docker 이미지 빌드

docker push: docker 이미지를 레지스트리에 업로드

docker run: docker 이미지를 기반으로 컨테이너를 생성하고 실행

docker login: docker 계정 로그인

docker image ls: docker 이미지 목록들을 확인

docker tag: docker 이미지에 이름 또는 태그를 할당

docker pull: docker 이미지를 레지스트리에서 가져온다.

 

docker host = docker server 

도커 컨테이너를 실행하는 데 사용되는 시스템으로 도커 엔진이 설치되어 있는 머신 또는 가상머신을 의미

컨테이너 간 통신을 관리, 도커 호스트는 호스트 운영체제와 네트워크와 상호작용하고 컨테이너가 실행되는 환경을 제공

 

docker registry

도커 이미지를 저장하고 관리하기 위한 중앙 저장소로 도커 이미지는 컨테이너화된 애플리케이션을 실행하기 위한 파일 시스템과 실행 환경을 포함하고 있다.

이미지들을 중앙에서 관리하고 공유할 수 있는 플랫폼, 도커 레지스트리를 사용하면 이미지를 쉽게 관리하고 배포할 수 있으며 여러 사용자와 협업해 이미지를 공유할 수도 있다.

 

docker deamon

클라이언트에서 요청한 도커 명령어를 처리하고 도커 컨테이너를 관리하는 백그라운드 프로세스이다.

도커 엔진과 상호작용해 컨테이너의 생성, 실행, 중단 삭제를 처리한다. 주로 서버에서 실행되면 도커 API 요청을 받고 이미지, 컨테이너, 네트워크 등 관리를 담당한다. 도커 데몬은 컨테이너의 생명주기를 관리하고 리소스 할당, 네트워크 연결 등의 작업을 처리한다.

docker deamon 명령어를 통해 docker deamon이 수행되고 있음을 확인할 수 있다.

 

docker image

도커 컨테이너를 실행하기 위한 파일과 설정 정보를 포함하는 컨테이너의 템플릿을 의미한다.

자신의 이미지를 가질 수 있고 다른 사람이 만든 이미지를 가져와 사용할 수도 있다. 이 이미지는 레지스트리에 게시된다.

이미지는 도커파일이라는 텍스트 파일에 정의되고 도커 이미지를 생성하는 데 사용된다.

도커 레지스트리에서 관리되고 저장된다.

도커 허브는 도커가 제공하는 공개 레지스트리로 다른 사람들과 도커 이미지를 공유하고 검색할 수 있는 장소이다.

도커 이미지는 컨테이너를 생성하고 실행하기 위해 사용된다.

도커 클라이언트를 사용해 이미지를 다운로드하고 컨테이너를 생성할 수 있다.

이미지는 컨테이너의 기반이 되고 여러 개의 컨테이너를 동시에 실행하거나 스케일링할 수 있다.

도커 이미지는 애플리케이션을 쉽게 배포하고 관리할 수 있는 도구이다.

이미지를 빠르게 구축하고 공유함으로 개발과 운영의 효율성을 높일 수 있다.

 

docker container

실행 가능한 이미지 인스턴스를 의미한다.

컨테이너는 컨테이너 간의 격리된 환경에서 실행되며 호스트와 독립적으로 실행될 수 있다.

애플리케이션의 이식성과 확장성이 향상되고 리소스 사용이 최적화된다.

 

docker hub

도커 컨테이너 이미지를 공유하고 관리하기 위한 클라우드 기반 레지스트리

도커 허브를 사용하면 컨테이너 이미지를 업로드, 다운로드와 공유할 수 있으며 도커 허브는 공식정인 이미지 저장소로써 다양한 언어, 프레임워크, 데이터베이스 등의 컨테이너 이미지를 제공한다.

사용자는 도커 허브에서 이미지를 검색하고 필요한 이미지를 사용할 수 있다. 도커 허브는 개인 및 조직용 계정을 제공하며 이미지를 관리하고 접근 권한을 제어할 수 있다. 

https://hub.docker.com/

 

Docker Hub Container Image Library | App Containerization

Increase your reach and adoption on Docker Hub With a Docker Verified Publisher subscription, you'll increase trust, boost discoverability, get exclusive data insights, and much more.

hub.docker.com

Explore에서 원하는 컨테이너 이미지를 제공받을 수 있다.

 

dockerfile

도커 이미지를 만들고 빌드하기 위한 텍스트 파일이다. 컨테이너 이미지를 성하는데 필요한 모든 단계와 명령을 정의한다.

도커 파일은 명령을 작성해 이미지를 빌드하는 방법을 지정한다.

일반적으로 도커 파일은 기본 이미지를 지정하고, 필요한 패키지를 설치하고, 파일을 복사하며 명령을 실행하는 등 작업을 수행한다.

각 명령은 도커 파일에서 한 줄씩 작성되고 이전 단계의 결과를 기반으로 수행된다.

도커 파일을 사용하면 반복적이고 일관적인 컨테이너 이미지 빌드 프로세스를 자동화할 수 있다. 도커 파일을 작성하고 빌드하면 도커 엔진이 자동으로 이미지를 생성하고 저장할 수 있다.

https://docs.docker.com/reference/dockerfile/

 

Dockerfile reference

Find all the available commands you can use in a Dockerfile and learn how to use them, including COPY, ARG, ENTRYPOINT, and more.

docs.docker.com

도커 파일 작성은 이 래퍼런스를 통해 자세하게 알아볼 수 있다.

 

이제 실제 프로젝트에서 도커 파일 생성하고 배포해 보자.

본 포스팅은 스프링부트로 빌드하겠다.

 

개발 환경

Project: Gradle - Groovy

Language: Java 21

Spring Boot: 3.2.3

Packaging: Jar

 

프로젝트 루트 경로에 Dockerfile을 생성한다.

FROM openjdk:21

WORKDIR /app

CMD ["./gradlew", "clean", "build"]

VOLUME /app/storefile

ARG JAR_FILE=build/libs/*.jar

COPY ${JAR_FILE} app.jar

EXPOSE 8080

ENTRYPOINT ["java","-jar","app.jar"]

FROM - openjdk 21 기반이 되는 이미지를 지정했다.

CMD - Gradle을 사용해 빌드를 실행하는 명령어

VOLUME - 컨테이너 내에 /app/storefile 디렉터리를 볼륨으로 설정

ARG - Gradle로 빌드한 jar 파일의 위치를 변수로 설정

COPY - JAR_FILE 변수에 지정된 파일을 app.jar로 컨테이너에 추가

EXPOSE - 컨테이너가 사용할 포트를 설정 8080으로 설정했다.

ENTRYPOINT - 컨테이너가 실행될 때 기본적으로 실행될 명령어를 실정

 

 

컨테이너 이미지를 생성한다.

dock build -t <컨테이너 이미지 이름>.

 

생성한 후 Docker Desktop에서 생성된 이미지를 확인한다.

 

컨테이너를 생성한다. 

docker run -d --name <컨테이너 이름> -p 8080:8080 <실행할 이미지 이름>

docker run 도커 이미지를 실행하는 명령어

-d  컨테이너를 백그라운드에서 실행하도록 설정

-p *:* 호스트 기기의 포트와 컨테이너의 포트를 연결

 

명령어 실행 후 컨테이너에 이미지가 올라간 것을 확인할 수 있다.

 

컨테이너를 실행하고 애플리케이션이 실행 잘 되는지 확인한다.

 

 

 

 

애플리케이션도 api도 모두 작동을 잘하는 것을 확인할 수 있다.

 

바로 잘 된 것 같겠지만 도커를 배포하면서 에러가 있어서 꽤 어려움을 겪었었다.

우선 첫 번째 오류로는 필자가 프로젝트에서 Mysql을 사용하는데

mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

도커에서 이런 오류 때문에 실행되지 않았다.

이유로는 yml에 설정에서 

url: jdbc:mysql://127.0.0.1:3306/project?serverTimezone=Asia/Seoul

 

mysql에 연결한 부분이 문제가 있었다. 인텔리제이에서 서버를 실행했을 땐 애플리케이션이 실행이 잘 됐었다.

yml에 설정된 부분에서 로컬 접속은 잘 됐었지만 도커에서 mysql에 연결할 때 도커에 맞는 연결 설정을 해야 하기 때문에 연결 오류가 문제 됐던 것이다.

그러므로 도커에서 연결할 수 있도록 yml을 바꿔주면 연결된다.

url: jdbc:mysql://host.docker.internal:3306/project?serverTimezone=Asia/Seoul

도커에서 내부적으로 mysql을 연결할 수 있게 설정해 주면 된다.

설정을 하고 다시 도커를 켜면 실행이 잘 된다.

 

다음 오류로는 

org.thymeleaf.exceptions.TemplateInputException: Error resolving template

프로젝트에서 다른 페이지로 넘어가는데 이런 오류가 나오면서 도커로 실행한 애플리케이션은 실행되지 않았다.

원인은 컨트롤러에 요청을 처리하는 핸들러의 리턴 경로를 /로 시작하면 viewResolver에서 /처리를 IDE에서는 해주었지만 jar 배포 시에는 처리를 못해주는 게 문제였다.

같은 오류를 찾는 사람들을 찾다 Springboot 2.0.4의 레퍼런스에 문제점이 대두된 적 있었다는 것을 알 수 있었다.

controller의 리턴 값의 /를 제거함으로 오류를 해결했다. 이로 인해 레퍼런스나 이슈들을 찾아보는 게 중요하단걸 알 수 있었다.

 

마지막 오류는 필자의 애플리케이션에서는 파일을 저장하는 로직이 있다.

이때 저장하면 파일을 로컬 저장소에 저장하는 방식인데 저장 시에 저장되지 않고 

Error occurred while storing file

에러 메시지가 나왔다. 로컬 저장소에 저장도 안 되고 이유를 알아보니 애플리케이션이 호스트 시스템의 로컬 디렉터리에 파일을 저장하려고 시도했으나 도커 컨테이너 내에서 실행될 때는 호스트 시스템의 경로가 아닌 컨테이너 내부의 경로를 사용해야 하는 것을 알 수 있었다.

yml의 파일 경로를 로컬 저장소로 두었었는데 파일 경로를 Dockerfile의 VOLUME과 맞추었고 이미지를 다시 빌드하고 컨테이너를 실행해서 이 문제를 해결했다. 배포하기 전에는 모르는 것들이었는데 배포하면서 생기는 문제점들을 알게 되었고 개발과 배포상의 차이에 대해서도 이해하게 되었고 앞으로 개발하면서도 더욱 유의하며 개발할 수 있을 것 같다.

 

여기까지 도커와 도커 배포, 배포에 생긴 이슈에 대해 알아보았다. 

'Docker' 카테고리의 다른 글

Jlaner 개발 Docker 사용과 TroubleShooting  (13) 2024.09.02
multi-mudule 도커 (kafka)  (0) 2024.06.22
springboot Docker Ec2에 배포하기  (0) 2024.04.28