inblog logo
|
parangdajavous
    Docker

    [Docker] 2. Dockerfile

    김미숙's avatar
    김미숙
    Jul 30, 2025
    [Docker] 2. Dockerfile
    Contents
    ✅ Dockerfile이란?🧱 대표적인 명령어✅ 요약실습 0 - Apache 실행Bind MountCopyVolume

    ✅ Dockerfile이란?

    • 도커 이미지를 만들기 위한 설정 파일(스크립트)
      • 이미지를 어떻게 만들 것인지 절차를 정의한 설계도
    • Dockerfile은 텍스트 기반의 명령어 모음 파일로, 우리가 원하는 환경이나 애플리케이션을 자동으로 이미지로 빌드할 수 있게 도와준다

    🧱 대표적인 명령어

    명령어
    설명
    FROM
    어떤 이미지를 기반으로 만들 것인지 지정 (예: nginx, ubuntu, openjdk)
    WORKDIR
    작업 디렉토리를 설정 (이후 모든 명령은 이 경로 기준으로 실행됨)
    COPY
    호스트의 파일/디렉토리를 이미지 안으로 복사
    ADD
    COPY와 유사하지만 압축 해제 가능, URL도 가능
    RUN
    이미지 빌드 도중에 실행할 명령어 (예: apt install, npm install)
    CMD
    컨테이너가 실행될 때 실행할 명령어
    ENTRYPOINT
    CMD처럼 실행 명령을 지정하지만, 더 고정된 실행 환경을 원할 때 사용
    ENV
    환경변수 설정
    EXPOSE
    컨테이너가 사용하는 포트 명시 (실제 포트 개방은 아님)

    ✅ 요약

    • Dockerfile = 이미지 설계도
    • FROM으로 시작해서 CMD나 ENTRYPOINT로 마무리
    • 이 파일을 docker build 명령으로 실행해 이미지 생성
     

    실습 0 - Apache 실행

    • 설치만 하는 건 pull
      • docker pull nginx
    • 설치 포함 실행은 run
      • docker run -d -p 8000:80 nginx
      • docker run -dit -p 8080:80 httpd
        notion image
        notion image
        notion image
        notion image

    Bind Mount

    ✅ Mount란?

    • 데이터를 컨테이너에 연결하는 방식 전체

    ✅ Mount 방식 2가지

    방식
    설명
    Bind Mount
    호스트의 특정 경로를 컨테이너 내부 경로와 연결
    Volume
    도커가 관리하는 독립된 저장소 (컨테이너 재시작해도 유지됨)

    ✅ Bind Mount란?

    • Mount 방식 중 하나
    • 호스트(내 컴퓨터)의 특정 디렉토리나 파일을 컨테이너 안에 연결(mount)하는 방법

    ✅ 특징

    항목
    설명
    📂 위치
    호스트의 직접 지정한 경로를 사용 (예: C:/workspace/project)
    🔁 양방향 접근
    컨테이너에서 수정한 파일이 호스트에도 반영되고, 반대로도 가능
    🔧 주 용도
    로컬 개발 시 코드 수정 사항을 바로 반영하고 테스트할 때
    🔥 주의할 점
    권한 관리나 OS별 경로 차이로 오류가 생길 수 있음
    🗑 컨테이너 삭제 시
    데이터는 사라지지 않음 (호스트에 있기 때문)

    ✅ Bind Mount가 필요한 이유?

    • 컨테이너 안에서 만든 파일이 컨테이너 삭제되면 사라짐 😢
      • → 데이터를 영구적으로 유지하고 싶을 때
    • 컨테이너에서 직접 호스트의 코드, 설정 파일 등을 읽고 쓰고 싶을 때
    • 개발 중 컨테이너 안 파일을 즉시 반영하고 싶을 때 (예: hot reload)
     

    실습1 - apache

    • ex01 폴더 내에 index.html 생성 후 apache의 index.html 위치 확인
      • notion image
        notion image
        notion image
    • ex01 폴더를 apache 웹 서버 폴더로 마운트
      • docker run -d -p 8000:80 -v c:/workspace/docker_lab/ex01:/usr/local/apache2/htdocs httpd
        → bash는 \ 인식 못함
        → 내가 생성한 폴더명 그대로 작성해야한다!
        docker_lab 을 docker-lab 라고 작성했더니 docker-lab 폴더를 생성하고 docker-lab 폴더를 마운트 함 : Windows 경로 지정 방식과 Docker 마운트 처리 방식의 차이에서 오는 현상
        🔍 왜 새로운 docker-lab 폴더가 만들어졌을까?
        -v c:/workspace/docker-lab/ex01:/usr/share/nginx/html
        이렇게 잘못된 경로를 입력했을 경우:
        👉 Windows에는 docker-lab 폴더가 없는데,
        Docker는:
        • "이 경로를 마운트하라고 했는데, 없네?"
        • 그러면 빈 디렉토리라도 만들어서 마운트해줘야겠다
          • → 그래서 docker-lab이라는 폴더를 새로 생성하고 마운트해버림
        ✅ 정리하면:
        상황
        결과
        호스트 경로가 정확할 때
        해당 폴더가 컨테이너에 마운트됨
        호스트 경로가 틀리거나 없음
        Docker가 빈 폴더를 새로 생성해서 마운트함
        🧩 경로를 지정할 땐 절대경로를 정확히 확인하고, bash는 슬래시(/), powershell은 백슬래시임(\)을 기억
    • 확인
      • notion image
        notion image
        notion image
         

    실습 2 - Nginx

    • Nginx 실행 확인
      • docker run -d -p 8000:80 nginx
        notion image
        notion image
        notion image
        notion image
    • Nginx의 index.html 위치 확인
      • docker exec -it 7ec6 bash
        → index.html은 /usr/share/nginx/html 폴더에 위치함
        notion image
        notion image
    • c:/workspace/docker_lab/ex01 로 마운트
      • docker run -d -p 8000:80 -v c:/workspace/docker_lab/ex01:/usr/share/nginx/html nginx
    notion image

    Copy

    💡
    마운트 보다 Copy 가 더 편하다

    ✅ Copy란?

    • Dockerfile에서 호스트 시스템의 파일이나 디렉토리를 도커 이미지에 복사하는 명령어

    ✅ 특징 요약

    항목
    설명
    사용 위치
    Dockerfile 내부
    복사 대상
    현재 Dockerfile 기준의 build context 내 파일만 가능
    경로 끝 슬래시 /
    생략해도 되고, 붙이면 "디렉토리로 복사" 의미가 더 명확함
    비교 vs ADD
    COPY는 복사만, ADD는 복사 + 압축 해제 기능 있음

    🧠 참고

    • Dockerfile과 같은 디렉토리에서 빌드할 때만 복사 가능
      • 외부 경로(ex. ../)는 사용할 수 없다
         

    실습 3 - apache

    • html 폴더 생성 후 index.html 파일 추가
      • <h1>ex03 test</h1>
    • Dockerfile 생성
      • 스크립트 작성해서 실행시킬 수 있음
      • 내가 원하는 이미지를 만들어내는 스크립트
      • 내 애플리케이션을 실행하기 위한 환경을 어떻게 만들지?를 정의한 설계도
      • 프로비저닝 - 완성품을 만들기 위한 준비과정 (서버가 만들어질 때 도커 파일을 읽어서 실행 후 만들어짐)
      • 이전에 작성한 Dockerfile
        # 기반 이미지 설정 # eclipse-temurin은 OpenJDK 공식 이미지 중 하나 # 21-jdk는 Java 21 버전의 JDK 환경 FROM eclipse-temurin:21-jdk # 작업 디렉토리 설정 # 이후 모든 명령은 /app 디렉토리 안에서 실행됨 # COPY, CMD, RUN 등 경로 기준이 /app이 됨 WORKDIR /app # 호스트의 JAR 파일 복사 # 현재 빌드 컨텍스트에서 build/libs/ 폴더에 있는 JAR 파일을 app.jar 이름으로 컨테이너에 복사 COPY build/libs/*.jar app.jar # 환경 변수 선언 # 추후 Java 실행 시 옵션을 커스터마이징할 수 있도록 환경변수 JAVA_OPTS 설정 # 예: -Xmx512m 같은 JVM 옵션을 런타임에 주입 가능 ENV JAVA_OPTS="" # 컨테이너 시작 시 실행할 명령어 설정 # 쉘에서 명령 실행: java $JAVA_OPTS -jar app.j # 실제 실행 -> java -jar app.jar ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
        ✅ 요약
        명령어
        설명
        FROM
        Java 21 JDK가 설치된 베이스 이미지 사용
        WORKDIR /app
        작업 디렉토리를 /app으로 설정
        COPY
        빌드된 .jar 파일을 이미지에 복사
        ENV
        JVM 옵션을 환경변수로 설정 (필요 시 확장 가능)
        ENTRYPOINT
        컨테이너 실행 시 Spring Boot 앱을 시작
        • JAR 파일 기반의 자바 서버 애플리케이션을 도커 이미지로 만들어 실행
        • 실행 흐름:
            1. Java 21 환경에서
            1. JAR 파일 복사하고
            1. java -jar 명령으로 실행
        FROM httpd COPY ./htdocs /usr/local/apache2/htdocs CMD ["httpd-foreground"]
        notion image
        🧱 Dockerfile 핵심 구조
        # 1. 베이스 이미지 설정 FROM node:18-alpine # 2. 작업 디렉토리 설정 WORKDIR /app # 3. 필요한 파일 복사 COPY package*.json ./ RUN npm install # 4. 소스 코드 복사 COPY . . # 5. 앱 실행 포트 지정 (옵션) EXPOSE 3000 # 6. 컨테이너 시작 시 실행될 명령어 CMD ["npm", "start"]
        🔍 각 명령어 설명
        명령어
        의미
        FROM
        어떤 이미지를 기반으로 만들 것인지 (ex: ubuntu, node, nginx 등)
        WORKDIR
        이후 명령어들이 실행될 작업 디렉토리 설정
        COPY
        호스트(내 컴퓨터) → 이미지로 파일 복사
        RUN
        이미지 빌드 과정에서 실행할 명령어 (예: RUN npm install)
        EXPOSE
        컨테이너가 사용하는 포트를 문서화 (실제 포트 개방 아님)
        CMD
        컨테이너가 실행될 때 자동으로 실행할 명령어
        📦 사용 흐름
        1. Dockerfile 작성
        1. docker build -t my-app .
          1. → Dockerfile 기반으로 이미지 생성
        1. docker run -p 8080:3000 my-app
          1. → 이미지로 컨테이너 실행
    → 기존 순수한 이미지에 docker build 명령어를 통해 이미지를 구워내면서 실행됨
    • Docker image build
      • docker build -t webserver .
        → -t webserver: 생성될 이미지에 태그(tag) 로 webserver라는 이름을 붙임
        → .: 현재 디렉토리에 있는 Dockerfile을 기준으로 빌드
        notion image
    • 이미지 확인
      • docker images
        notion image
        notion image
         
    • 이미지로 컨테이너 실행
      • docker run -p 8080:80 webserver
        notion image
        notion image
    • 확인
      • notion image
     

    실습 4 - Nginx

    • Nginx 실행해서 설정파일 확인
      • docker run -d -p 8080:80 nginx
        notion image
    • Nginx 설정파일 위치 확인
      • docker exec -it 1538 bash
        → 설정파일의 위치: /etc/nginx/
      • nginx.conf
        • 기본 nginx 설정파일
        • NGINX의 최상위 설정 파일(main config)
        • user nginx; worker_processes auto; error_log /var/log/nginx/error.log notice; pid /run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; }
          → include /etc/nginx/conf.d/*.conf; : etc/nginx/conf.d/ 경로에 있는 모든 .conf 파일을 읽는다 / 개별 서버 설정들을 불러오는 구조
          → default.conf 같은 파일을 conf.d 폴더에 넣으면 자동으로 포함 됨
         
      • default.conf
        • NGINX에서 기본으로 제공하거나, 사용자가 정의하는 서버 블록(server block) 설정 파일
        • 보통 도메인이나 포트에 따라 요청을 처리하는 규칙을 여기에 정의
        • 위치: /etc/nginx/conf.d/default.conf
        • server { listen 80; listen [::]:80; server_name localhost; // -> 기본 도메인 이름 설정 (보통 개발 환경에서 사용) #access_log /var/log/nginx/host.access.log main; location / { root /usr/share/nginx/html; // -> 웹서버가 요청에 응답할 때 기준이 되는 디렉토리 (여기서는 html 파일들이 있는 경로) index index.html index.htm; // -> 루트 경로(/) 요청 시 우선적으로 찾을 기본 파일 리스트. 첫 번째로 index.html을 찾고 없으면 index.htm } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; // -> 에러 발생 시 보여줄 HTML 파일 지정 location = /50x.html { root /usr/share/nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }
        • /usr/share/nginx/html : 웹서버 폴더 경로
        • index.html index.htm; : 해당 파일을 읽는다
        • 기존 설정파일을 복사한 후 내가 원하는 대로 설정한다
        •  
    • 설정파일 수정
      • conf.d 폴더 생성 후 default.conf 파일 만들어서 내용 복사 → 수정
      • server { listen 5000; listen [::]:5000; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }
        → 포트를 8080에서 5000으로 수정
     
    • Dockerfile
      • FROM nginx COPY ./html/ /usr/share/nginx/html COPY ./conf.d/ /etc/nginx/conf.d CMD ["nginx", "-g", "daemon off;"]
        → COPY ./html/ /usr/share/nginx/html: 로컬의 html/ 폴더에 있는 정적 파일들을 컨테이너 내부의 /usr/share/nginx/html 로 복사
        → COPY ./conf.d/ /etc/nginx/conf.d: 로컬의 conf.d/ 폴더에 있는 설정 파일들 (default.conf 등)을 컨테이너의 /etc/nginx/conf.d 디렉토리로 덮어씌워서 기본 설정을 원하는 방식으로 커스터마이징
        → CMD ["nginx", "-g", "daemon off;"]: nginx를 포그라운드 모드로 실행해서 컨테이너가 계속 살아있도록 설정
        🔧 daemon on vs daemon off 차이
        옵션
        의미
        사용 목적
        daemon on
        NGINX를 백그라운드에서 실행 (기본값)
        일반 리눅스 환경에서 NGINX를 서비스처럼 돌릴 때 사용
        daemon off
        NGINX를 포그라운드에서 실행
        Docker 컨테이너 내부에서 사용 (컨테이너 유지 목적)
        🚀 왜 Docker에서는 daemon off를 써야 할까?
        Docker는 기본적으로 포그라운드 프로세스가 없으면 컨테이너가 자동 종료됨
        그래서 nginx가 백그라운드에서 실행되면, Docker 입장에선 “앗? 실행 중인 게 없네?” 하고 바로 컨테이너를 꺼버린다
        👉 그래서 CMD ["nginx", "-g", "daemon off;"]로 포그라운드에서 nginx를 실행해야 컨테이너가 계속 살아있고 웹서버도 유지됨
        Docker 컨테이너는 반드시 하나의 포그라운드 프로세스를 실행하고 있어야 컨테이너가 계속 유지된다
        • Docker는 하나의 메인 프로세스(PID 1)를 기반으로 작동하며, 이 메인 프로세스가 종료되면 컨테이너도 즉시 종료
        • 백그라운드로 실행되면 "컨테이너 안에서 실행할 게 없다"고 판단해서 종료됨.
        ✅ 결론
        도커 컨테이너는 포그라운드 실행을 원칙으로 한다.
        (즉, 컨테이너 안에서 메인 프로세스가 계속 떠 있어야 한다.)
        notion image
    • 이미지 확인
      • docker images
        notion image
    • 이미지로 컨테이너 실행
      • docker run -p 5000:5000 nginxserver
    notion image

    Volume

    ✅ Volume이란?

    • Mount 방식 중 하나
    • 컨테이너의 데이터를 지속적으로 저장하거나 공유하기 위해 사용하는 저장 공간
    • 도커가 관리하는 컨테이너 외부 저장소로, 컨테이너가 삭제돼도 데이터는 남아있도록 해주는 중요한 기능
    • 컨테이너 데이터를 안전하게 보존하고, 재사용·공유·백업까지 쉽게 가능하게 해주는 핵심 기능

    ✅ 왜 Volume을 쓰나?

    이유
    설명
    🎯 데이터 유지
    컨테이너를 지우거나 재시작해도 데이터는 유지됨
    🛡️ 안정성
    도커가 관리하므로, 경로/권한 문제 없이 안정적으로 동작
    📤 데이터 공유
    여러 컨테이너가 동일한 볼륨을 공유 가능
    🔄 백업·복원 용이
    docker volume 명령으로 쉽게 백업하거나 이동 가능
    🔍 호스트 디렉토리 의존 ↓
    바인드 마운트보다 안전하고 독립적

    📊 Bind Mount vs Volume

    구분
    Bind Mount
    Volume
    📍 저장 위치
    호스트의 지정된 경로 (예: C:/myfolder)
    Docker가 관리하는 경로 (예: /var/lib/docker/volumes/)
    🛠️ 생성 방법
    직접 경로 지정 (-v /host/path:/container/path)
    이름 지정 또는 자동 생성 (-v myvolume:/container/path)
    🔧 유연성
    호스트 디렉토리를 자유롭게 지정 가능
    Docker가 내부적으로 관리 (보안/관리 편리)
    🔐 보안
    보안 취약점 우려 있음 (호스트 파일 접근 가능)
    상대적으로 안전 (Docker 내부 디렉토리 관리)
    🔁 백업/이동성
    직접 복사해야 함
    docker volume 명령어로 백업/이동 쉬움
    🧪 테스트 용도
    개발 환경에서 코드 실시간 반영 등 유리
    배포/운영 환경에서 데이터 유지에 유리
    🔍 사용 명령
    -v C:/code:/app
    -v myvol:/data 혹은 docker volume create myvol

    ✅ 요약 정리

    • Bind Mount
      • 호스트의 특정 폴더를 그대로 컨테이너에 연결
      • 💡 실시간 코드 수정 등 개발 환경에 유리
    • Volume
      • Docker가 자체적으로 생성/관리하는 디렉토리
      • 💡 데이터 유지 및 운영 환경에 적합
     
    Share article
    Contents
    ✅ Dockerfile이란?🧱 대표적인 명령어✅ 요약실습 0 - Apache 실행Bind MountCopyVolume

    parangdajavous

    RSS·Powered by Inblog