## Dockerfile 이란? 이미지가 어떤 단계를 걸쳐 빌드되는지 적힌 텍스트 파일. 프로젝트 최상위 디렉터리에 두는 것이 관례이다. `docker build`를 명령하면 이 파일에 나열된 명령문을 차례대로 수행하여 이미지가 생성된다. ## CLI 형식 ``` docker build -t [생성할 이미지 이름] [Dockerfile 경로] ``` ## Dockerfile 주요 명령 ### 참고 : [Yaml 문법](https://lejewk.github.io/yaml-syntax/) | 명령어 | 의미 | 예시 | | | | | | ------------------------------------------ | -------------------------------- | ------------------------------------------------------------------------------ | ---------------- | ---------------------------- | --- | ----- | | `FROM [이미지 이름]` | 베이스가 되는 이미지 지정 | `FROM nginx` | | | | | | `MAINTAINER [작성자 정보]` | 이미지를 유지보수하는 사람 정보 지정 | `MAINTAINER John Doe` | | | | | | `RUN [커맨드]` | 명령 실행 | `RUN apt-get update && apt-get install -y wget` | | | | | | `COPY [소스] [타겟]` | 로컬 파일 복사 | `COPY ./app /usr/src/app` | | | | | | `ADD [소스] [타겟]` | 로컬 파일 또는 URL 추가 (압축 파일 해제 가능) | `ADD http://example.com/file.tar.gz /tmp/` | | | | | | `WORKDIR [작업 디렉터리]` | 작업 디렉터리 설정 | `WORKDIR /usr/src/app` | | | | | | `ENV [환경 변수 이름] [값]` | 환경 변수 설정 | `ENV NODE_ENV production` | | | | | | `EXPOSE [포트]` | 컨테이너가 사용하는 포트 공개 | `EXPOSE 80` | | | | | | `CMD [실행 명령]` | 컨테이너가 시작될 때 실행할 명령 설정 | `CMD ["npm", "start"]` | | | | | | `ENTRYPOINT [실행 명령]` | 컨테이너가 시작될 때 실행할 명령 설정 (CMD보다 우선) | `ENTRYPOINT ["nginx", "-g", "daemon off;"]` | | | | | | `VOLUME [경로]` | 컨테이너와 호스트 간 데이터 공유를 위한 디렉터리 설정 | `VOLUME /var/log` | | | | | | `USER [사용자]` | 실행할 사용자 지정 | `USER appuser` | | | | | | `RUN apk --no-cache add [패키지]` | Alpine Linux에서 패키지 설치 | `RUN apk --no-cache add curl` | | | | | | `ARG [인자]` | 빌드 중에 전달되는 인자 정의(= 이후는 기본값) | `ARG version=latest` | | | | | | `LABEL [키=값]` | 이미지에 메타데이터 추가 | `LABEL version="1.0" description="My custom image"` | | | | | | `COPY --from=[이미지] [소스] [타겟]` | 빌드 중 다른 이미지에서 파일 복사 | `COPY --from=builder /app/build /usr/share/nginx/html` | | | | | | `RUN [커맨드] | | true` | 에러 발생해도 빌드 계속 진행 | `RUN command_that_might_fail | | true` | | `HEALTHCHECK [옵션] CMD [명령]` | 컨테이너의 건강 상태를 확인하는 명령 설정 | `HEALTHCHECK --interval=5m CMD curl --fail http://localhost | | exit 1` | | | | `RUN [커맨드] && rm -rf /var/lib/apt/lists/*` | 캐시 크기 줄이기 위해 패키지 설치 후 불필요한 파일 삭제 | `RUN apt-get update && apt-get install -y wget && rm -rf /var/lib/apt/lists/*` | | | | | | `STOPSIGNAL [시그널]` | 컨테이너 중지 시 전송되는 시그널 설정 | `STOPSIGNAL SIGTERM` | | | | | ## 사용 예시 ### Node JS 기반 서버 이미지 생성 ``` # Node.js XX 버젼 FROM node:XX # 작업 디렉터리 설정 WORKDIR /usr/src/app # 소스 코드 복사 COPY . . # 패키지 설치 RUN npm install # 애플리케이션 실행 명령 설정 CMD ["npm", "start"] ``` ### Spring Boot 서버 이미지 생성(Gradle 🐘) ``` # OpenJDK 17을 베이스 이미지로 선택 FROM adoptopenjdk:17-jdk-hotspot # 볼륨 명시적으로 설정 VOLUME /data # JAR 경로 받는 ARG 설정(기본값 포함) ARG JAR=build/libs/my-spring-boot-app.jar # JAR 파일을 컨테이너로 복사 # Gradle은 build/libs/ 여기에 jar을 생성함 COPY ${JAR} app.jar # 빌드된 JAR 파일 실행 CMD ["java", "-jar", "app.jar"] ``` - build.gradle 에 아래의 설정을 추가하면 빌드 후 jar 파일의 이름이 고정됨. ``` bootjar { archivesBaseName = 'my-spring-boot-app' archiveFileName = 'my-spring-boot-app.jar' } ``` ### MySQL 서버 이미지 생성 ``` FROM mysql:8.0 ENV MYSQL_ROOT_PASSWORD=[비밀번호] ENV MYSQL_DATABASE=[DB 이름] ENV MYSQL_USER=[유저 이름] ENV MYSQL_PASSWORD=[비밀번호] RUN { \ echo '[mysqld]'; \ echo 'character-set-server=utf8mb4'; \ echo 'collation-server=utf8mb4_unicode_ci'; \ echo 'skip-host-cache'; \ echo 'skip-name-resolve'; \ } > /etc/mysql/my.cnf EXPOSE 3306 VOLUME /var/lib/mysql ```