이번에 배우게 된 Spring + Vue를 활용해 간단한 주식 시장 웹서비스를 구현하고자 한다.
이 글은 구현한 애플리케이션의 구조 설명 및 시연 화면등으로 구성될 예정이다.
그 중 BackEnd의 Spring과 FrontEnd Vue의 도커파일 생성에 대한 내용이다.

cd stock
./gradlew bootJar
stock-0.0.1-SNAPSHOT.jar 파일 생성
파일이 2개가 있다.

Dockerfile 이라는 파일 만들기(확장자 ❌)
파일 안에 아래 내용 작성
# Java 21 기반의 Spring Boot 애플리케이션용 Dockerfile
FROM openjdk:21
# 작업 디렉토리 설정
WORKDIR /app
# 빌드된 jar 파일을 컨테이너로 복사
# COPY <복사할_파일_이름> <컨테이너_내_위치와_이름>
COPY build/libs/stock-0.0.1-SNAPSHOT.jar app.jar
# 외부에서 접근할 포트 지정
EXPOSE 8080
# 환경 변수 설정 (선택 사항)
# ENV SPRING_PROFILES_ACTIVE=prod
# jar 파일 실행
ENTRYPOINT ["java", "-jar", "app.jar"]
stock 폴더 터미널에서 명령어 실행
# Docker 이미지 빌드
docker build -t stock-backend .
# 컨테이너 실행
docker run -d -p 8080:8080 --name backend stock-backend
확인용 터미널
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
stock-backend latest 2d3f782c6dc6 15 minutes ago 905MB
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
59905eb558c2 stock-backend "java -jar app.jar" 25 seconds ago Up 25 seconds 0.0.0.0:8080->8080/tcp backend
cd stock-front
npm install
npm run build
똑같이 Dockerfile 생성자 없이 생성
# 1단계: 빌드용
FROM node:20-alpine AS builder
WORKDIR /app
# package.json과 lock 파일 복사
COPY package*.json ./
# 의존성 설치
RUN npm install
# 전체 프로젝트 복사
COPY . .
# Vite 빌드
RUN npm run build
# 2단계: Nginx 사용해 정적 파일 서빙
FROM nginx:stable-alpine
# 빌드된 파일을 Nginx HTML 경로로 복사
COPY --from=builder /app/dist /usr/share/nginx/html
# 포트 오픈 (기본: 80)
EXPOSE 80
# 컨테이너 시작 시 Nginx 실행
CMD ["nginx", "-g", "daemon off;"]
빌드 & 실행 명령어
# Docker 이미지 빌드
docker build -t stock-frontend .
# 컨테이너 실행 (포트는 5173 → 80으로 매핑)
docker run -d -p 5173:80 --name frontend stock-frontend
Trouble Shooting
로컬 개발환경에서는
const res = await.get('http://localhost:8080/api/stocks)이런식으로 되어있지만
도커로 프론트를 띄웠을 때는 Vue 앱이 localhost:8080이 아닌
Nginx 컨테이너에서 실행중이라 실패
따라서 코드를 변경해줘야 한다axios.post('/api/players/login', { ... }) axios.get('/api/players') -> axios.post(`${import.meta.env.VITE_API_URL}/api/players/login`, { ... }) axios.get(`${import.meta.env.VITE_API_URL}/api/players`)
위와 같은 형식으로 전부 수정해주고
.env.production을 만들어
Vite가 도커 빌드시 자동으로 인식해서 import.meta.env.VITE_API_URL에 주입해주게 한다.
VITE_API_URL=http://localhost:8080
앱에서도 확인이 가능하다

Vue(front)와 Spring Boot(back)의 Dockerfile은 분리되어 있고
그 둘을 함께 실행하고 관리하려면 docker-compose.yml 을 사용하는 것이 정석
stock-project/
├── stock-front/ # Vue 프론트 (Dockerfile 존재)
├── stock/ # Spring Boot 백엔드 (Dockerfile 존재)
└── docker-compose.yml
docker-compose.yml 작성
version: '3.8'
services:
backend:
build: ./stock
container_name: stock-backend
ports:
- "8080:8080"
networks:
- stock-net
frontend:
build: ./stock-front
container_name: stock-frontend
ports:
- "5173:80"
depends_on:
- backend
networks:
- stock-net
networks:
stock-net:
driver: bridge
build : 각각의 Dockerfile이 있는 디렉토리 경로
ports : 외부 → 내부 포트 매핑 (브라우저 접속용)
depends_on : 프론트가 백엔드보다 나중에 실행되도록 보장
networks : 두 컨테이너가 서로 통신할 수 있도록 구성
Trouble Shooting
front의 .env.production의 API 주소 수정
VITE_API_URL=http://backend:8080backend는 docker-compose 내부에서 자동으로 DNS로 연결한다.
외부에서 보면 8080이지만, 컨테이너 안에서는 http://backend:8080으로 통신한다.
포트 충돌 가능성과 네트워크 혼란 관리의 편의성등을 위해
기존 컨테이너 정지
docker stop frontend
docker rm frontend
docker stop backend
docker rm backend
빌드 및 실행
docker-compose build
docker-compose up -d
docker ps 할 경우
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4798fbc4f487 java-frontend "/docker-entrypoint.…" 27 seconds ago Up 26 seconds 0.0.0.0:5173->80/tcp stock-frontend
ac76e9fd4e78 java-backend "java -jar app.jar" 27 seconds ago Up 26 seconds 0.0.0.0:8080->8080/tcp stock-backend


