Docker 이미지를 빌드하기 위한 명령어들을 작성한 파일이다.
Docker 컨테이너를 실행하는 데 필요한 모든 파일과 설정을 포함한 패키지
이미지를 빌드하기 위해서는, Dockerfile이 존재하는 디렉토리에서 다음 명령을 실행하면 된다.
docker build -t [이미지 이름]:[태그] .
빌드한 이미지로 컨테이너를 실행할 수 있다.
docker run -d -p 4000:80 --name mycontainer myimage:tag
// -p 4000:80: 호스트의 4000 포트와 컨테이너의 80 포트를 연결.
// 이는 외부에서 컨테이너의 80 포트에 접근할 때 사용한다.
Docker Compose는 여러 컨테이너를 동시에 구성하는데 사용되는 도구로, docker-compose.yml 파일을 통해 서비스, 네트워크, 볼륨 등을 정의한다.
다음은 현재 개발중인 프로젝트의 docker-compose.yml
파일이다.
services: # 실행할 모든 컨테이너 서비스를 정의한다.
postgres: # 첫번째 서비스의 이름
image: postgres:16 # 이 서비스가 사용할 도커 이미지, Docker Hub에서 제공한다.
container_name: postgres
environment: # 컨테이너 내에서 사용할 환경변수
POSTGRES_USER: cluster23
POSTGRES_PASSWORD: cluster23
POSTGRES_DB: quant-helper
ports: # 호스트 머신(이 컨테이너를 담고 있는 PC) - 컨테이너간의 포트 매핑
- "5432:5432"
volumes: # 데이터를 영구적으로 저장하기 위한 볼륨
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
api: # 두번째 서비스의 이름
build: # Docker 이미지를 빌드하기 위한 설정
context: .
dockerfile: ./docker/api/Dockerfile
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/quant-helper
SPRING_DATASOURCE_USERNAME: cluster23
SPRING_DATASOURCE_PASSWORD: cluster23
container_name: api
ports:
- "8080:8080"
depends_on: # api 서비스가 실행되기 이전에 postgres 서비스가 먼저 실행되어야 한다.
- postgres
networks: # backend 네트워크에 연결한다.
- backend
networks: # backend network는 driver로 bridge를 사용한다.
backend:
driver: bridge
volumes: # postgres_data 볼륨 정의
postgres_data:
volumes
docker는 가상화 환경인 컨테이너에서 작업을 진행한다.
따라서, 모든 데이터는 컨테이너 내부에만 존재하게 된다.
➜ 컨테이너를 삭제하면 작업한 모든 데이터가 날라간다.
컨테이너가 삭제되어도 데이터를 유지하고 싶은 경우에 사용하는 것이 volume이다.
volume은 데이터를 외부로 링크하는 기능이다.
위의 경우, postgres 서비스의 데이터는/var/lib/postgresql/data
에 저장된다.
network
도커의 네트워크란 Docker 컨테이너 간의 통신을 관리하고 격리하기 위한 기능이다.
지금 Docker에는 2가지의 서비스가 존재한다.
이 두개의 컨테이너를 연결하기 위해서는 수정해줘야 할 사항들이 몇가지 존재한다.
application.yml
에서 url: jdbc:postgresql://postgres:5432/quant-helper
로 수정environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/quant-helper
SPRING_DATASOURCE_USERNAME: cluster23
SPRING_DATASOURCE_PASSWORD: cluster23
현재 Dockerfile이 존재하는 위치는 다음과 같다.
/Users/Ruffles/Downloads/quantHelper/docker/api/Dockerfile
Dockerfile은 다음과 같이 작성했다.
FROM gradle:jdk17 AS build
WORKDIR /app
COPY --chown=gradle:gradle . /app
RUN gradle build --no-daemon
FROM openjdk:21-slim
WORKDIR /app
COPY --from=build /app/build/libs/*.jar /app/spring-boot-application.jar
ENTRYPOINT ["java","-jar","/app/spring-boot-application.jar"]
Stage 1
Stage2
Directory '/app' does not contain a Gradle build
Dockerfile
은 현재 api 폴더 내에 존재한다.
따라서, api 폴더 내에서 Docker를 빌드 했더니 위와 같은 오류가 발생했다.
Dockerfile이 위치한 디렉토리에서 빌드를 실행하면, 이 경로가 기본적으로 빌드 컨텍스트가 된다.
➜ COPY --chown=gradle:gradle . /app
명령이 실행되지 않는다.
따라서, 위치를 루트로 바꾼뒤에 실행해야한다.
cd /Users/Ruffles/Downloads/quantHelper
docker build -t api -f docker/api/Dockerfile .
22 StockTest > testSaveStock() FAILED
58.22 java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:180
58.22 Caused by: org.springframework.beans.factory.BeanCreationException at AbstractAutowireCapableBeanFactory.java:1786
58.22 Caused by: liquibase.exception.DatabaseException at SpringLiquibase.java:288
58.22 Caused by: org.postgresql.util.PSQLException at ConnectionFactoryImpl.java:354
58.22 Caused by: java.net.UnknownHostException at NioSocketImpl.java:572
docker-compose up -d
를 사용했더니 계속해서 이런 오류가 발생했다.
처음에는 postgresql이랑 연결이 잘못된줄 알고 Dockerfile과 docker-compose 파일을 계속 수정했는데, 결론은 이거였다.
test 폴더 내부에는 application.yml이 존재하지 않는다.
따라서, test를 제외시켜줘야 빌드가 수행된다.
Dockerfile에 RUN gradle build --no-daemon -x test
를 추가했더니 해결되었다.