2026. 2. 8. 17:26ㆍ도커
이전 글에서 개발 환경을 Docker Compose를 이용해서 구축했습니다.
배포 시에 이 docker-compose.yml을 그대로 EC2 서버에 올리면 동작은 하겠지만 여러 가지 문제가 있을 수 있습니다.
어떤 문제가 생길지 예상해보고 하나씩 해결해 보겠습니다.
현재 방식으로 배포했을 때 문제점
배포 과정을 단순히 보면 아래의 과정이 됩니다.
# EC2 접속
# 프로젝트 클론
git clone https://github.com/project/project.git
# 컨테이너 실행
docker compose up -d
실제로 동작은 하겠지만 docker-compose.yml을 보면 문제가 보입니다.
services:
...
backend:
image: gradle:9-jdk17
container_name: backend-container
working_dir: /app
ports:
- "8081:8081"
volumes:
- /backend:/app
command: sh -c "(sleep 10; gradle build --continuous -x test) & gradle bootRun --no-daemon"
environment:
- SPRING_PROFILES_ACTIVE=DEV_ENV
depends_on:
mysql-service:
condition: service_healthy
redis-service:
condition: service_healthy
networks:
- app-network
...
우선 백엔드 서비스만 보더라도
- 약 700MB의 gradle 이미지를 그대로 다운로드 받음
- 소스코드가 서버에 그대로 노출되어 보안이 좋지 않음
- 개발환경(DEV_ENV)으로 배포
- --continuous 모드가 들어있어 계속 EC2의 CPU를 사용함.
이러한 문제점이 있습니다.
여기서 설정 관련 문제는 docker-compose.yml을 분리해서 해결하고,
보안 및 리소스 문제는 Dockerfile을 이용해 해결해 보겠습니다.
docker-compose.yml 분리하기
현재는 docker-compose.yml이 하나만 있습니다.
로컬에서 개발할 때는 문제가 없겠지만 배포할 때는 문제가 생깁니다.
1. 스프링 환경설정 문제
environment:
- SPRING_PROFILES_ACTIVE=PROD_ENV # 배포용으로 변경
배포를 위해서는 스프링 환경을 배포용으로 변경해야 하는데,
배포를 위해 이 값을 바꾸고 'git push'하면 다른 PC에서 pull 했을 때 로컬 개발 환경이 깨지게 됩니다.
2. auto reload를 위한 --continuous 문제
서버에서는 코드를 수정할 일이 크게 없습니다.
하지만 --continuous 모드로 인해서 불필요하게 CPU를 계속 사용하게 됩니다.
이러한 문제들로 인해서 개발용, 배포용으로 파일을 분리해 줄 필요가 있습니다.

이렇게 기존의 docker-compose.yml을 2개로 분리해 주고
docker-compose.dev.yml의 내용은 기존대로 유지하고, docker-compose.prod.yml의 내용은 아래와 같이 바꿔줍니다.
...
command: gradle bootRun --no-daemon # continuous 모드 제거
environment:
- SPRING_PROFILES_ACTIVE=PROD_ENV # 배포 환경
...
Dockerfile로 이미지 만들기
현재 방식의 동작과정
EC2 서버:
1. git clone 또는 git pull로 소스코드 다운로드
2. gradle 이미지 다운로드
3. 소스코드를 /app에 마운트
4. 빌드 후 실행
위 방식으로 인해 아래와 같은 결과가 나옵니다.
- EC2 서버에 전체 소스코드가 올라가므로 보안 취약
- gradle 이미지 다운로드 필요로 인한 리소스 낭비
배포 시에는 JAR파일을 실행만 하면 되기 때문에 JRE + JAR만 있으면 됩니다.
Dockerfile 방식
로컬 PC:
1. 소스코드 빌드해서 JAR 파일 생성
2. JAR파일만 포함한 이미지를 Dockerfile로 빌드
3. 완성된 이미지 Docker Hub에 업로드
EC2 서버:
1. 완성된 이미지 다운로드
2. 컨테이너 실행
Dockerfile 방식으로 변경하면 이미지만 다운로드해서 바로 컨테이너를 실행하면 되므로
- 소스코드가 노출되지 않음
- 이미지 크기 감소
- 빌드를 로컬에서 하므로 불필요한 빌드 도구를 포함하지 않음
Dockerfile을 이용한 이미지 빌드 및 배포
1. Dockerfile 작성
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY build/libs/app.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
- FROM: 베이스 이미지 지정
- WORKDIR: 컨테이너 안에서 작업할 디렉토리 설정
- COPY: build/libs/app.jar를 복사
- ENTRYPOINT: 컨테이너 실행 시 실행할 명령어.
2. 이미지 빌드
docker build -t myapp:latest .
- -t myapp:lastest : 이미지 이름과 태그 지정
- . : 현재 디렉토리 (backend/)에서 Dockerfile을 찾는다고 지정
3. DockerHub 업로드
# 1. Docker Hub 로그인
docker login
# 2. 이미지에 태그 달기
docker tag myapp:latest [계정]/myapp:0.1
# 3. push
docker push [계정]/myapp:0.1
4. docker-compose.prod.yml 변경
생성한 이미지를 DockerHub에서 받아서 실행해야 하므로 docker-compose.prod.yml도 변경되어야 합니다.
# 변경 전
backend:
image: gradle:9-jdk17
container_name: backend-container
working_dir: /app
ports:
- "8081:8081"
volumes:
- ./backend:/app
command: sh -c "(sleep 10; gradle build --continuous -x test) & gradle bootRun --no-daemon" # ENTRYPOINT로 대체되므로 제거
environment:
- SPRING_PROFILES_ACTIVE=PROD_ENV
depends_on:
mysql-service:
condition: service_healthy
redis-service:
condition: service_healthy
networks:
- app-network
# 변경 후
backend:
image: [계정]/myapp:0.1
container_name: backend-container
ports:
- "8081:8081"
environment:
- SPRING_PROFILES_ACTIVE=PROD_ENV
depends_on:
mysql-service:
condition: service_healthy
redis-service:
condition: service_healthy
networks:
- app-network
- image: gradle이미지에서 직접 만든 이미지로 변경
- working_dir: Dockerfile의 WORKDIR이 대신함
- volume: JAR가 이미지 안에 포함되어 있으므로 소스코드 마운트 불필요
- command: Dockerfile의 ENTRYPOINT가 대신함
간단한 예제
1. 간단한 프로젝트 생성
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello World";
}
}


간단한 프로젝트를 만들고 Dockerfile을 추가한 후 빌드해서 JAR 파일을 만들어줍니다.
2. Docker 빌드해서 이미지를 만들어줍니다.
docker build -t myapp:latest .
위 명령어를 입력하면

이와 같이 이미지가 생성된 걸 확인할 수 있습니다.
3. Docker Hub 업로드
이 상태에서 이미지를 push 하면 아래와 같은 에러가 발생합니다.

계정 이름이 없기 때문에 Docker Hub 공식 이미지 저장소 [docker.io/library/]에 올리려고 시도를 했지만,
해당 저장소에 push 권한이 없기 때문에 발생하는 에러입니다.
따라서 아래와 같은 명령어를 입력해서 이미지에 태그를 붙여줍니다.
docker tag myapp:latest [username]/myapp:0.1
이는 기존 도커 이미지에 별칭을 생성하는 것으로 이미지 원본을 복사하는 것이 아니라 동일한 이미지를 가리키는 이름만 하나 더 만드는 방식입니다.
그 후 다시 push하면 성공적으로 올라갑니다.
'도커' 카테고리의 다른 글
| Docker를 이용해 프로젝트 컨테이너화 하기 - 코드 수정 시 자동 반영 적용 (auto reload) (0) | 2026.01.20 |
|---|---|
| Docker를 이용해 프로젝트 컨테이너화 하기 - docker-compose.yml 작성 (1) | 2026.01.20 |
| 도커 이미지와 컨테이너 (1) | 2025.07.08 |
| 볼륨과 바인드 마운트 (0) | 2025.07.08 |
| 도커 컴포즈(Docker Compose) (0) | 2025.07.08 |