도커는 애플리케이션을 컨테이너화하여 배포, 실행을 용이하게 하는 플랫폼이다. 컨테이너는 애플리케이션과 그 의존성을 패키지화하여 어느 환경에서든 동일하게 동작할 수 있도록 도와준다.
- 프로젝트에 적용하면 좋은 점
- 환경 일관성: 개발, 테스트, 배포 환경이 동일하므로, '내 컴퓨터에서는 되는데' 문제를 방지할 수 있다.
- 이식성: 어떤 OS에서든 동일하게 실행할 수 있어, 여러 환경에서의 호환성 문제를 해결한다.
- 분리 및 보안: 애플리케이션을 격리된 환경에서 실행함으로써 보안을 강화할 수 있다.
- 효율적인 리소스 사용: 가상 머신보다 훨씬 적은 리소스를 사용하여 시스템의 효율성을 높일 수 있다.내가 진행하는 과제는 연구실에서 진행하다보니 여러 컴퓨터를 옮겨다닐 일이 많다. 그래서 어느 환경에서든 동일하게 작동할 수 있도록 하는 도커의 적용은 필수적이라고 생각한다.
도커를 사용하기 위해서는 도커 파일이 필요하다.
# 첫 번째 스테이지: 의존성 설치
FROM python:3.9-slim-buster as builder
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /install
COPY requirements.txt .
RUN pip3 install --no-cache-dir --prefix="/install" -r requirements.txt
# 두 번째 스테이지: 최종 이미지 생성
FROM python:3.9-slim-buster
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ARG UID=1000
ARG GID=1000
RUN groupadd -g "${GID}" python \
&& useradd --create-home --no-log-init -u "${UID}" -g "${GID}" python
USER python:python
WORKDIR /home/python
COPY --from=builder /install /usr/local
COPY --chown=python:python . .
ARG FLASK_DEBUG
ENV FLASK_DEBUG=${FLASK_DEBUG}
EXPOSE 5000
CMD ["gunicorn", "-b", "0.0.0.0:5000", "-t", "500", "app:app"]
다른 도커 파일들이랑 좀 다른 모습을 알 수 있다. 왜냐하면 멀티 스테이지 기술을 활용하여서 도커 이미지의 크기를 줄였기 때문이다.
- 멀티 스테이지 빌드의 장점
- 이미지 크기 감소: 멀티 스테이지 빌드를 사용하면 불필요한 파일을 제거하여 최종 이미지 크기를 줄일 수 있다.
- 보안 향상: 빌드 단계에서만 필요한 도구와 의존성을 최종 이미지에서 제거함으로써 보안을 강화할 수 있다.
- 빌드 속도 개선: 불필요한 파일이 최종 이미지에 포함되지 않으므로 빌드 시간이 단축된다.
도커 파일을 만들고 빌드 하기전에 나는 .dockerignore를 추가하였다.
- .dockerignore의 장점
- 빌드 속도 향상: 불필요한 파일을 빌드 컨텍스트에서 제외함으로써 빌드 속도를 빠르게 한다.
- 이미지 크기 최소화: 불필요한 파일이 이미지에 포함되지 않아 이미지 크기를 줄일 수 있다.
- 보안 강화: 민감한 파일이 실수로 이미지에 포함되는 것을 방지하여 보안을 강화한다.
이제 아래 명령어를 이용하여서 이미지를 빌드 후 컨테이너로 실행하면 된다.
docker built -t 도커허브아이디/이미지이름:버전 ./
-t 태그는 도커 이미지에 유용한 이름을 붙여주는 역할을 한다.
docker run -p 5000:8080 <이미지 아이디>
로컬 포트와 컨테이너 포트를 매핑 시켜줘야 한다.
잘 실행되는 모습을 알 수 있다.
스프링도 마찬가지로 아래 도커 파일을 만들면 된다.
# Jar 파일 빌드
FROM eclipse-temurin:17 as builder
# 소스 코드와 Gradle Wrapper 복사
COPY gradlew .
COPY gradle gradle
COPY build.gradle .
COPY settings.gradle .
COPY src src
# Gradle Wrapper 실행 권한 부여
RUN chmod +x ./gradlew
# 애플리케이션 빌드
RUN ./gradlew bootJar
# Jar 실행
FROM eclipse-temurin:17-jre as runtime
# 사용자 및 그룹 생성
RUN addgroup --system --gid 1000 worker
RUN adduser --system --uid 1000 --ingroup worker --disabled-password worker
USER worker:worker
# 빌드된 Jar 파일 복사
COPY --from=builder /build/libs/*.jar app.jar
# 환경변수 설정
ENV PROFILE ${PROFILE}
# 포트 8080 열기
EXPOSE 8080
# 애플리케이션 실행
ENTRYPOINT ["java", "-Dspring.profiles.active=${PROFILE}", "-jar", "/app.jar"]
자신의 자바 버전을 기술 해주고 나머지는 해당 코드를 그대로 작성하면 될 것이다.
target
**/*.log
Dockerfile
.git
.gitignore
마찬가지로 .dockerignore 파일을 만들어준다.
주의해야할 점은 도커 컨테이너 내부에서 호스트 시스템의 네트워크에 접근하기 위해 host.docker.internal 주소를 사용해야한다. 이는 도커 컨테이너가 자체적인 네트워크 환경을 가지고 있어, 일반적인 localhost 주소로는 호스트 시스템에 접근할 수 없기 때문이다.
잘 실행 되는 모습이다.
이제 클라우드 타입에 데이터베이스 서버를 구축하고 local 환경이 아닌 dev 환경에서 실행해보자