Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- MVC요청플로우
- 전전긍긍
- 냄새라도
- 커뮤니티서버
- 공통기술
- JPA
- 공통규약
- 이벤트핸들러this
- string
- model
- 클린아키텍처
- TDD
- Ajax
- springsecurity
- OOP
- 문제선택근거
- AOP
- SpringLegacy
- index
- DDD
- 이벤트핸들러등록
- Transaction
- 단위테스트
- 로그백
- SEQUENCE
- 사면초가
- 설정세팅
- JDBC
- 디스크i/o
- MVC
Archives
- Today
- Total
개발이군고구마
[멱살잡고 DevOps] 3. Backend Dockerfile (docker compose/docker hub) 본문
728x90
아래와 같은 순서대로 배포 프로세스를 잡아갈 예정이다.
[Backend Dockerfile] <- 현단계
1. backend Dockerfile 작성 🎆
[AWS Front 설정]
2. S3 버킷 & CloudFront 배포 설정
[AWS EC2 설정]
3. EC2 인스턴스 프로비저닝
4. EC2 환경 구성 🎆
[CI/CD]
5. GitHub Actions CI/CD 구축 🎇
[테스트와 확장]
6. DNS 설정 및 최초 배포 테스트
7. 배포 환경 분리 (dev/prod)
우선 아래 사항들은 사전에 준비가 완료되어야 한다.
- AWS 계정, IAM 사용자/권한 확인 (프리티어로 사용예정)
- 도메인 준비(예: 가비아) 및 DNS 관리 권한 확보
- GitHub 저장소(backend, frontend) 및 Docker Hub 계정
- MongoDB Atlas 설정
IAM 사용자 권한

ㄴ GitHub Actions에서 AWS에 접근하기 위한 전용 IAM 사용자 생성
(예: AmazonS3FullAccess의 특정 버킷 버전, CloudFrontFullAccess 등)
1. nginx 설정 파일
events {
}
# 이벤트 설정 블록을 정의하며, 워커 프로세스 연결 관련 설정을 포함합니다.
http {
# HTTP 관련 설정 블록을 시작합니다.
upstream api {
# 'api'라는 이름의 업스트림 그룹을 정의합니다.
server backend:5000;
# backend 컨테이너의 5000 포트를 API 처리 서버로 지정합니다.
}
server {
# 가상 서버 설정을 정의합니다.
listen 80;
# HTTP 기본 포트(80)에서 요청을 수신합니다.
server_name 도메인이름;
# 해당 도메인 이름에 대한 요청을 처리합니다.
location /api/ {
# '/api/' 경로로 들어오는 요청을 처리하는 위치 블록을 시작합니다.
proxy_pass http://api;
# upstream 'api'로 모든 /api/ 요청을 전달합니다.
proxy_set_header Host $host;
# 원본 요청의 Host 헤더를 백엔드로 전달합니다.
proxy_set_header X-Real-IP $remote_addr;
# 클라이언트의 실제 IP 주소를 백엔드로 전달합니다.
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 프록시 체인에 클라이언트 IP 정보를 추가하여 전달합니다.
proxy_set_header X-Forwarded-Proto $scheme;
# 요청이 사용한 프로토콜(http/https)을 백엔드로 전달합니다.
}
}
}
💠 nginx는 별도의 Dockerfile을 생성하지 않음
- 공식 이미지의 장점 -> 보안 유지보수 편리
- 현 사이트는 리버스 프록시와 기본 헤더·캐싱 설정 정도만 사용, 즉 커스텀 이미지 (모듈추가, 런타임 변경 불가 패키지 포함 등) 만들필요 없음
- HTTPS 종단(Offload)을 CloudFront에서 처리함
- 추가 모듈·패키지 요구사항이 없으므로, 매번 빌드할 이유 없이 “풀-매니지드” 형태로 운영이 편리
2. 환경변수 파일
MONGO_URI="mongodb+srv://[사용자]:[비번]@[클러스터이름]/mern?retryWrites=true&w=majority&appName=[app이름]"
PORT=5000
3. Dockerfile
👁🗨 멀티 스테이징으로 build/run 하여 이미지 경량화 수정 필요
# 1. 베이스 이미지
FROM node:18-alpine
# 2. 작업 디렉토리
WORKDIR /usr/src/app
# 3. 패키지 설치 (캐시 활용)
COPY package*.json ./
RUN npm install --production #
# 4. 소스 복사
COPY . .
# 5. (선택) 빌드 타임 기본값 설정
# .env가 없을 때만 이 기본값을 사용합니다.
# 포트는 공개하지 않는 것이 더 좋다고 함
# 6. 포트 개방
EXPOSE ${PORT}
# 7. 시작 명령
CMD ["node", "app.js"]
4. docker-compose.yml
version: '3.8'
services:
backend:
build:
context: .
dockerfile: Dockerfile
# 로컬에서 .env 파일 쓸 경우 이렇게 참조 가능
env_file:
- .env
ports:
- "${PORT}:${PORT}"
restart: unless-stopped
nginx:
image: nginx:alpine
depends_on:
- backend
ports:
- "80:80"
- "443:443"
# nginx.conf 파일을 프로젝트 루트/nginx/nginx.conf 로 두고 마운트
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
5. dockerignore
# Node.js dependencies - 로컬에 설치된 패키지 제외
node_modules
# 환경 변수 파일 (비밀 정보)
.env
# IDE, OS 메타데이터
.vscode
.DS_Store
# 로그
npm-debug.log*
yarn-debug.log*
6. docker 이미지 빌드해보기
# 이미지 빌드
docker build --tag allweneedfarm-backend:local --file Dockerfile .
# 빌드 로그 & 이미지 목록 확인
docker images allweneedfarm-backend:local
# 컨테이너 실행
docker run -d --name test-backend -e PORT=5000 -p 5000:5000 allweneedfarm-backend:local
# 도커 컴포즈 빌드 backend와 nginx가 함께 올라가는지 점검
docker-compose up --build
7. Docker 이미지 빌드 & 레지스트리 업로드
❎ Nginx 는 따로 docker hub에 올릴 필요 없나?
공식 Nginx 이미지를 쓰고 있다면 이미 Docker Hub에 있으니까
- 직접 빌드하거나 관리하지 않아도
- docker-compose up 하면 자동으로 최신 버전을 pull
커스텀 이미지가 아닐 때는 푸시가 불필요
- 직접 Dockerfile을 작성해서 Nginx를 커스터마이징하지 않았다면
- 별도의 이미지 빌드·태깅·푸시 과정 없이 바로 공식 이미지를 참조만 하면 충분
# 이미지 빌드
docker build --tag {도커hub아이디}/{이미지이름}:{태그} --file Dockerfile .
# v1.0.0 은 릴리즈 버전 규칙(Semantic Versioning) 배포 자동화
docker tag {도커hub아이디}/{이미지이름}:{태그} {도커hub아이디}/{이미지이름}:v1.0.0
# 이미지 푸시
docker push {도커hub아이디}/{이미지이름}:{태그}
docker push {도커hub아이디}/{이미지이름}:v1.0.0


[빌드 과정에서 발생한 오류 모음]
💥 ✘ Container backend-nginx-1 발생


ㄴ Docker Desktop 설정 변경 (WSL based integration으로)
💥 컨테이너 실행 오류
docker: Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint test-backend: Bind for 0.0.0.0:5000 failed: port is already allocated
docker: Error response from daemon: Conflict. The container name "/test-backend" is already in use by container "3c138c1b807615f4730721835c76ccefe5d306f53b9d8d93df543154aad414f3". You have to remove (or rename) that container to be able to reuse that name.
ㄴ 기존에 실행되었던 포트/컨테이너가 제거가 되지 않아서 발생하는 오류
# 1) 현재 실행 중인 컨테이너 확인 docker ps
# → 만약 test-backend 외에 5000번을 쓰고 있는 컨테이너가 있다면,
docker stop <CONTAINER_ID>
docker rm <CONTAINER_ID>
# (1) 중지된 포함 모든 컨테이너 목록에서 확인
docker ps -a --filter "name=test-backend"
# (2) 필요하다면 컨테이너 중지
docker stop test-backend
# (3) 컨테이너 제거
docker rm test-backend
🌐 이미지 빌딩 완료
백엔드와 nginx가 이미지가 작동하는 컨테이너

💥 컨테이너 health 체크 오류
ㄴ app.js에 404 처리용 “catch-all” 미들웨어가 잘못 작성
// 변경 전
// router를 미들웨어로
app.use("/api/farms", farmRoutes); // 받아온 라우팅
app.use("/api/users", userRoutes);
// 지원되지 않는 라우트 처리
app.use((req, res, next) => {
const error = new HttpError("Could not find this route", 404);
// ← next(error)나 res.send() 없이 이 함수가 그냥 종료.
});
// 변경 후
// catch-all 미들웨어보다 위에 위치
app.get("/api/health", (req, res) => {
res.status(200).send("OK");
});
app.use((req, res, next) => {
const error = new HttpError("Could not find this route", 404);
next(error); // ← 반드시 호출!
});

'Cloud Deploy' 카테고리의 다른 글
| [멱살잡고 DevOps] 5. AWS EC2 설정 (0) | 2025.07.21 |
|---|---|
| [멱살잡고 DevOps] 4. AWS S3/Cloudfront 설정 (1) | 2025.07.18 |
| [멱살잡고 DevOps] 2. 배포 아키텍처 설계 (0) | 2025.07.15 |
| [멱살잡고 DevOps] 1. Docker Compose와 ECS (컨테이너의 분산 배포) (2) | 2025.07.14 |
| [GIT] rebase 또는 merge main 으로 브랜치 현행화 (0) | 2025.06.01 |