이제 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
실행
먼저 도커 파일 작성을 알아보도록 하겠습니다.
Dokcerfile은 도커 이미지를 생성하는 데 사용되는 파일입니다. Dockerfile에 정의한 명령어들은 이미지 레이어를 형ㅇ성하며, 각 레이어는 이전 레이어를 기반으로 합니다.
처음 적는 명령어FROM
은 베이스 이미지로, 매우 중요합니다.
Docker에서는 Dockerfile이라는 특정한 파일명을 사용하도록 규정하고 있고 있습니다.
대소문자 주의!
Dockerfile의 위치는 project root에 위치하는게 좋습니다.
#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"]
베이스 이미지를 결정하는 명령어 입니다. 해당 프로젝트는 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
는docker 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
안에는 없기 때문입니다.
container
내Files
를docker desktop
으로 보면/build/libs/docker-example-0.0.1-SNAPSHOT.jar
가 없는 것을 볼 수 있습니다.
local
에 있는jar파일
을 해당 위치로복사
해주면 됩니다.
여기에서는
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]
과container
의port
를 바인딩 해주면 됩니다. 저는 tomcat을 8081로 띄웠기 때문에 8081로 바인딩하겠습니다.
docker run -p
[local-port(Host-port)]
:[container port]
[image-name]
docker run -p 8081:8081 section01-example
옵션을 추가해서 컨테이너를 실행해보겠습니다.
접근이 잘 되는것을 확인할 수 있습니다.
가장 처음 봤던
Dockerfile
에서 사용했던WORKDIR
과ARG
에 대해 설명을 적어보려 합니다.
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
로 시작하는 것이다.
동일하게 도커 컨테이너 실행 명령어를 실행한 다음
container
의Files
를 보면
해당 디렉토리에COPY
된 것을 볼 수 있다.
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로 빼서 사용한 것이다.
위 사진처럼 Dockerfile을 만들고 명령어docker build . -t [image-name]
을 실행하던 중 발생한 문제입니다.
해결법은 간단합니다. Dockerfile 시작이 LABEL author="loky1" 로 시작하기 때문에 발생한 문제입니다. FROM ...
명령어를 가장 위로 올려주면 됩니다.
OS가
window
라면 실행을 검색하신 후%AppData%
를 입력한 후 확인을 눌러줍니다.
도커를 프로그램을 삭제 후
[user]/[AppData]/[Local]/[Docker]
파일을 완전히 삭제해준 후 다시 설치합니다.
다음으로
Docker Desktop
을 실행하면 오류가 날 수 있습니다. 그 때는CMD
창을 열어--unregister docker-desktop-data
명령어 입력 후
등록 취소 중입니다, / 작업을 완료했습니다
가 뜬 후 다시Docker Desktop
을 실행하면 됩니다.