docker 공부 시작하기 [spring-boot] 도커 파일로 컨테이너 실행하기- (1)

xxx-sj·2023년 11월 21일
0

도커

목록 보기
1/3

📕 시작

이제 docker를 공부를 해야 될 것 같아서 정리도 하고, 제가 겪은 것들을 공유하기 위해 이 글을 시작합니다.
잘못된 부분이 있거나 궁금하신 부분이 있으시다면 언제든지 말씀해주세요

📕프로젝트 구성

프로젝트는 간단하게 start.spring.io 에서 spring web 만 dependency로 갖도록 하여 구성하였습니다.

이 후에 도커로 띄운 서버 테스트를 위해 간단한 controller를 만들어 주었습니다.

@RestController
public class HelloController {

   @GetMapping("/")
   public String hello() {
       return "hello";
   }
}

잘 실행되는지 run 실행해 본 후 ./gradle build 빌드를 통해 jar 파일을 만들어 줍니다.

📙실행과정

도커 실행 과정은 크게 보면 다음과 같습니다.

도커 파일 작성 -> build 를 통해 이미지 생성 -> run을 통해 이미지를 가진container 실행

먼저 도커 파일 작성을 알아보도록 하겠습니다.

📕Dockerfile

Dokcerfile은 도커 이미지를 생성하는 데 사용되는 파일입니다. Dockerfile에 정의한 명령어들은 이미지 레이어를 형ㅇ성하며, 각 레이어는 이전 레이어를 기반으로 합니다.
처음 적는 명령어 FROM은 베이스 이미지로, 매우 중요합니다.

📒Dockerfile 말고 다른이름은 안되나요??

Docker에서는 Dockerfile이라는 특정한 파일명을 사용하도록 규정하고 있고 있습니다.
대소문자 주의!

📒Dockerfile의 위치는??

Dockerfile의 위치는 project root에 위치하는게 좋습니다.

📙작성된 Dockerfile

#Dockerfile

FROM openjdk:11-jdk

WORKDIR /app

ARG PATH=./build/libs

COPY ${PATH}/docker-example-0.0.1-SNAPSHOT.jar ${PATH}/docker-example-0.0.1-SNAPSHOT.jar
CMD ["java", "-jar", "./build/libs/docker-example-0.0.1-SNAPSHOT.jar"]

📙하나씩 알아보기

📒FROM

베이스 이미지를 결정하는 명령어 입니다. 해당 프로젝트는 java11 을 사용하기 때문에 FROM openjdk:11-jdk 를 사용하였습니다.

#Dockerfile

FROM openjdk:11-jdk

Docker 파일에 FROM 명령어만 적어서 이미지를 만들고 run 해보도록 하겠습니다.

docker 명령어를 사용할 때는 Dockerfile이 있는 root에서 명령어를 실행하였습니다.
이미지 생성 명령어는 다음과 같습니다
docker build . -t [image-name] -f [dockerfile-name]
docker build . -t section01-example

도커 이미지는 docker images 명령어를 통해 생성된 이미지를 확인하실 수 있습니다.

📗실행해보기

생성된 이미지로 컨테이너를 실행해보도록 하겠습니다. 명령어는 다음과 같습니다

docker run [image-name]
docker run section01-example

FROM만 작성된 Dockerfile을 이용하여 컨테이너를 실행했을 때 아래와 같습니다.

간단하게 생각해서 실행하는 명령이나 서비스를 실행하는 내용이 없기 때문입니다.

다음으로 실행하는 명령어를 추가해보겠습니다.

📒CMD

CMDdocker run 명령어를 실행 할 때 실행되는 명령어 입니다.
CMD로 실행할 명령어는 다음과 같습니다

java -jar /build/libs/docker-example-0.0.1-SNAPSHOT.jar
gradle build를 통해 빌드된 jar 파일을 실행하는 것입니다.

#Dockerfile

FROM openjdk:11-jdk
CMD ["java", "-jar", "/build/libs/docker-example-0.0.1-SNAPSHOT.jar"]

이제 다시 이미지를 만들어서 컨테이너를 생성하여 실행해보겠습니다. 이 전과 같습니다.

docker build . -t section01-example , docker run section01-example

에러 내용을 보면 /build/libs/docker-example-0.0.1-SNAPSHOT.jar 해당 jarfile을 access 할 수 없다는 내용입니다.
❗️왜 이런 오류가 났을까요??❗️

간단히 생각해보면 다음과 같습니다. 이미지로 생성된 container 도 하나의 새로운 공간[컴퓨터] 입니다.
즉, /build/libs/docker-example-0.0.1-SNAPSHOT.jar 위치의 jar 파일은 local[Host OS] 에만 있을 뿐 container 안에는 없기 때문입니다.

containerFilesdocker desktop으로 보면 /build/libs/docker-example-0.0.1-SNAPSHOT.jar 가 없는 것을 볼 수 있습니다.
section01-example image

📗어떻게 해야할까?

local에 있는 jar파일을 해당 위치로 복사 해주면 됩니다.

📒COPY

여기에서는 local [Host OS]에 위치한 jar file을 복사해서 container이동시키는 명령어 입니다.

COPY [local(Host OS) file] [container location]

#Dockerfile

FROM openjdk:11-jdk
COPY ./build/libs/docker-example-0.0.1-SNAPSHOT.jar /build/libs/docker-example-0.0.1-SNAPSHOT.jar
CMD ["java", "-jar", "/build/libs/docker-example-0.0.1-SNAPSHOT.jar"]

Dockerfile을 수정하였으니 동일하게 이미지를 만들고 컨테이너를 실행해보겠습니다.


COPY 명령어를 통해 해당 위치에jarfile이 복사된 것을 확인할 수 있습니다.

tomcat이 뜨는것 까지 해결되었습니다. 톰캣 서버도 떴으니 이제 다음으로 port 8081 로 떠있는 서버에 브라우저에서 접근해보도록 하겠습니다.

❗️하지만 사이트에 연결할 수 없다고 나오네요.. 왜 일까요??❗️
위에서 말한 것처럼 이미지로 생성된 container도 하나의 새로운 공간[컴퓨터]이기 때문에
local[Host OS]container연결해 주어야 합니다.

📗그러면 어떻게 해야 할까??

간단합니다. container를 실행할 때 옵션으로 local[Host OS]containerport를 바인딩 해주면 됩니다. 저는 tomcat을 8081로 띄웠기 때문에 8081로 바인딩하겠습니다.

docker run -p [local-port(Host-port)]:[container port] [image-name]
docker run -p 8081:8081 section01-example

옵션을 추가해서 컨테이너를 실행해보겠습니다.



접근이 잘 되는것을 확인할 수 있습니다.

📒추가적으로

가장 처음 봤던 Dockerfile에서 사용했던 WORKDIRARG 에 대해 설명을 적어보려 합니다.

📒WORKDIR

WORKDIR 명령어는 linux 명령어 cd와 같다고 생각하면 쉽다. 말 그대로 working directory이다. 그렇다면 왜 사용하는가?

사용이유는 다음과 같다. 처음 베이스이미지를 이용해 만든 파일들이 있을텐데, 해당 파일들과 구분하기 위해서 라고 생각이 들며, 만약 같은파일이름 으로 COPY할 경우 베이스 이미지에서 만든 파일이 덮어쓰기가 되어버린다.

#Dockerfile

FROM openjdk:11-jdk
WORKDIR /app
COPY ./build/libs/docker-example-0.0.1-SNAPSHOT.jar ./build/libs/docker-example-0.0.1-SNAPSHOT.jar
CMD ["java", "-jar", "./build/libs/docker-example-0.0.1-SNAPSHOT.jar"]

여기서는 조금 달라지는데, WORKDIR를 이용하여
디렉토리를 이동 하였기 때문에 COPY 부분과 CMD 부분이 달라진다.

기본에는 COPY./build/libs/docker-example-0.0.1-SNAPSHOT.jar /build/libs/docker-example-0.0.1-SNAPSHOT.jar 에서 ./build/libs/docker-example-0.0.1-SNAPSHOT.jar ./build/libs/docker-example-0.0.1-SNAPSHOT.jar 로 변경되었다.

이유는 다음과 같다. WORKDIR/app으로 이동하였기 때문에 /build/libs에서 ./build/libs로 변경된 것이다. /build/libs를 하게되면 절대경로 /build 부터 시작하게 되어버리는 것이고, ./build를 하게 되면 현재 디렉토리인 /app에서 시작하는 것. 다시말해, ./build/libs -> /app/build/libs 가 되는 것이다.

동일하게 CMD도 마지막에 ./build로 변경된 이유도 같은 이유이다. 현재 working directory/app이기 때문에 현재 디렉토리에서 이동하는 것으로 ./build/libs로 시작하는 것이다.

동일하게 도커 컨테이너 실행 명령어를 실행한 다음 containerFiles를 보면

해당 디렉토리에 COPY된 것을 볼 수 있다.

📒ARG

ARG는 말그대로 argument, 인자이다. 해당 Dockerfile을 실행할 때 사용되는 변수선언할 때 사용한다.

#Dockerfile

FROM openjdk:11-jdk
ARG PATH=./build/libs
WORKDIR /app
COPY ${PATH}/docker-example-0.0.1-SNAPSHOT.jar ${PATH}/docker-example-0.0.1-SNAPSHOT.jar
CMD ["java", "-jar", "./build/libs/docker-example-0.0.1-SNAPSHOT.jar"]

여기에서는 ./build/libs가 중복되어서 따로 ARG로 빼서 사용한 것이다.

📕시행착오

📒ERROR: failed to solve: no build stage in current context


위 사진처럼 Dockerfile을 만들고 명령어docker build . -t [image-name] 을 실행하던 중 발생한 문제입니다.

📗해결법

해결법은 간단합니다. Dockerfile 시작이 LABEL author="loky1" 로 시작하기 때문에 발생한 문제입니다. FROM ... 명령어를 가장 위로 올려주면 됩니다.

📒starting 무한로딩

📗해결법

OS가 window라면 실행을 검색하신 후 %AppData%를 입력한 후 확인을 눌러줍니다.

도커를 프로그램을 삭제 후[user]/[AppData]/[Local]/[Docker] 파일을 완전히 삭제해준 후 다시 설치합니다.

다음으로 Docker Desktop을 실행하면 오류가 날 수 있습니다. 그 때는 CMD창을 열어 --unregister docker-desktop-data 명령어 입력 후
등록 취소 중입니다, / 작업을 완료했습니다 가 뜬 후 다시 Docker Desktop을 실행하면 됩니다.

참고

https://ttl-blog.tistory.com/761#%EC%96%B4%EB%96%BB%EA%B2%8C%20%ED%95%B4%EA%B2%B0%ED%95%98%EB%82%98%EC%9A%94%3F%20%F0%9F%A7%90-1

profile
틀려도 일단 기록하자

0개의 댓글