[Spring+Vue] Stock-Application (4)

ww_ung·2025년 4월 2일

SKALA

목록 보기
19/25

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

그 중 BackEnd의 Spring과 FrontEnd Vue의 도커파일 생성에 대한 내용이다.

Backend

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

Frontend

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

앱에서도 확인이 가능하다

Front + Back

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:8080

backend는 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

시연 사진

0개의 댓글