docker

[Dorker] Dockerfile 작성하는 법

미스터 한뺑 2023. 5. 18. 17:55
반응형

DockerFile 명령어

FROM 생성할이미지의 베이스가되는 이미지

LABEL 이미지에 메타데이터를추가
WORKDIR 생성된 컨테이너 안에서 명령어를 실행할 디렉터리를 나타냄
COPY 호스트에서 이미지에 파일 복사하여 추가
ADD 호스트안에 있는 파일/디렉토리 추가, COPY와 다른점음 압축파일은 해제하고 추가하고, 또한 wget이라는 명령어를 이용하여 추가도 가능
EXPOSE 호스트와 연결할 포트 번호를 설정(보통 명령어run 에서 -p로 대체)
ENV 환경변수 설정
RUN 이미지를만들기 위해 컨테이너 내부에서 돌아갈 명령어 이미지가 완전 생성 되지 전에 실행 되는 명령어이다
CMD 컨테이너가 실행 되었을 때 바로실행되는 명령어 설정
ENTRYPOINT 컨테이너가 시작되었을 때 스크립트실행
VOLUME 호스트 주소와 마운트(DB는 파일을 가지고 있어야하기 때문에 마운트 필수)

 

1. FROM

생설할 이미지의 베이스가 되는 이미지이다.

FROM 이미지_이름[:태그]

여기서 이미지_이름은 기반이 되는 이미지의 이름이고, 선택적으로 태그를 지정할 수 있습니다. 태그는 이미지의 버전이나 레이블을 나타냅니다. 예를 들어, ubuntu:latestubuntu라는 이미지의 최신 버전을 사용한다는 의미입니다.

 

이미지에 OS, sql등 다양한 이미지를 넣을 수 있다.

 

 

2. LABEL

이미지에 메타데이터를  추가한다.

FROM ubuntu:latest
LABEL maintainer="John Doe <johndoe@example.com>"
LABEL version="1.0"
LABEL description="This is a sample Docker image."

이 예제에서는 maintainer, version, description과 같은 메타데이터를 추가하고 있습니다. 이 정보들은 이미지에 대한 추가적인 설명이나 문서화에 사용될 수 있습니다.

LABEL 지시자를 사용하면 이미지를 쉽게 식별하고 문서화할 수 있으며, 이미지 관리와 협업을 용이하게 만들어줍니다.

메타데이터는 데이터에 대한 정보를 설명하는 데이터입니다. 즉, 데이터를 설명하는 데이터라고 할 수 있습니다.

 

 

3. WORKDIR

WORKDIR 경로

다음과 같은 형식으로 작성이 된다. workdir은 작업 디렉토리를 설절하는 지시자입니다. 작업 디렉토리는 Docker 컨테이너 내에서 실행중인 명령이 실행될 기본 디렉토리를 나타냅니다. 위에서 말하는 경로는 정대 경로나 대상 경로로 지정할 수 있다. workdir 사용하여 작업 디렉토리를 설정하면 run, cmd , copy, add... 등 작업 디렉토리를 기준으로 실행이 됩니다. 

 

4. COPY

COPY 소스_경로 대상_경로

copy를 사용하여 파일을 docker 이미지로 복사하면, 해당 파일은 Docker 컨테이너 내에서 사용 가능한 리소스로 포함됩니다. 또한 독립적으로 실행 가능한 이미지를 만들 수 있으며 , Docker 컨테이너를 배포하거나 공유할 때 필요한 모든 파일을 포함할 수 있다. 

 

 

5. ADD

ADD 소스_경로 대상_경로

add는 copy와 비슷한 역활을 수행하지만 add는 호스트머신의 파일이나 디렉토리를 docker 이미지 안으로 복사하는 것 외에도 다양한 기능을 가지고 있다 . 

- 소스 경로 : 복사할 파일이나 디렉토리 경로

- 대상 경로: docker이미지 내부에서 복사된 파일이나 디렉토리 경로 

 

add는 copy와 다른 점이다. 

  1. URL 다운로드: ADD는 웹 상의 파일을 다운로드하여 Docker 이미지로 복사할 수 있습니다. 예를 들어, ADD http://example.com/file.txt /app/과 같이 사용하여 웹에서 파일을 다운로드하고 /app/ 디렉토리로 복사할 수 있습니다.
  2. 자동 압축 해제: ADD는 일부 압축 형식에 대해 자동으로 압축을 해제할 수 있습니다. 예를 들어, .tar, .tar.gz, .tar.bz2, .tar.xz, .zip 등의 압축 파일을 ADD로 복사하면, Docker는 해당 압축 파일을 자동으로 압축 해제하여 이미지에 포함합니다.
  3. 원격 파일 복사: ADD는 원격 URL을 지정하여 파일을 복사할 수도 있습니다. 예를 들어, ADD https://example.com/file.txt /app/과 같이 사용하여 원격 서버의 파일을 복사할 수 있습니다.

그러나 일반적으로 파일 복사를 위하는거면 copy를 사용하는 것이 권장한다. copy는 add에 비해 더 명시적이고 예측 가능하며, 보안 측면에서도 더 안전한 방법이다. 

 

# 로컬 파일 복사

ADD app.py /app/
현재 디렉토리에 있는 app.py 파일을 Docker이미지의 /app/ 디렉토리로 복사

#Url 다운로드
ADD https://example.com/file.txt /app/
웹에서 file.txt 파일을 다운로드하여 Docker 이미지의 /app/ 디렉토리로 복사

# 압축파일 복사 및 자동 압축해제
ADD example.tar.gz /app/
example.tar.gz 압축 파일을 Docker 이미지의 /app/ 디렉토리로 복사하고, Docker는 자동으로 압축을 해제하여 이미지에 포함시킵니다.

 

6. EXPOSE

EXPOSE 포트번호/프로토콜

Docker 컨테이너가 특정 포트에서 서비스를 제공할 것임을 명시하는 역활을 한다. 해당 포트를 호스트 머신과 연결할 수가

있다. 

 

- 포트번호: 노출할 포트 번호 

- 프로토콜: 사용할 네트워크 프로토콜 기본값은 TCP이다. 

 

7. ENV

ENV 변수명 값

env는 환경변수를 정의하는 역활을 한다. 이것을 활용하여 환경 변수를 설정하면, 이 변수는 docker 이미지 내에서 사용되거나 실행 중인 컨테이너에서 사용될 수 있다. 

 

- 변수명 : 환경 변수의 이름

- 값 : 해당 변수에 할당될 값

값은 문자열로 지정되며, 환경변수는 런타임 시에 이 값으로 치환이 된다. 

 



ENV MY_VARIABLE=my_value
ENV DATABASE_HOST=localhost DATABASE_PORT=5432

이 예시에서는 ENV를 사용하여 세 개의 환경 변수를 정의하고 있습니다. 첫 번째 줄은 MY_VARIABLE이라는 환경 변수를 my_value로 설정하고 있습니다. 두 번째 줄은 DATABASE_HOSTDATABASE_PORT 환경 변수를 각각 localhost5432로 설정하고 있습니다.

Docker 이미지를 빌드하고 컨테이너를 실행하면 다음과 같은 결과가 나타납니다

yaml파일

My variable: my_value
Database host: localhost
Database port: 5432
Application is running with my_value

 

8. RUN

Docker 이미지를 빌드하는 동안 실행할 명령을 지정한다. 단계별로 명령을 실행하고 그결과 새로운 이미지 레이어로 커밋한다. 이미지를 생성하는 동안 필요한 패키지 설치, 소스 코드 컴파일, 설절 파일 생성 드의 작업을 수행한다. 

RUN 명령
RUN apt-get update
RUN apt-get install -y python3

위의 예시에서는 RUN 지시자를 사용하여 Ubuntu 패키지 관리자를 업데이트하고 python3를 설치하는 명령을 실행하고 있습니다

 

"run apt -get update " 와 "apt-get install"은 항상 같은  run 구문 안에 있어아한다 .

위에 예시 처럼  작성하면 캐시 문제가 생길 수 있고 apt-get install가 실패할 가능성도 있다. 이미지가 빌드 된 이후에 모든 레이어가 도카 캐시안에 들어가게 된다. ' apt-get intall ' 뒤에 구문을 추가 했다고 가정해보면 

# syntax=docker/dockerfile:1
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install -y curl nginx

도커는 이전 명령어와 수정된 명령어가 동이 할 때에만 이전단계의 캐시를 이용한다. 따라서 빌드가 캐시된 버전을 사용하기 때문에 apt-get update가 실행 되지 않는다. 그래서 이 빌드는 잠재적으로 오래된 버전의 'curl'과 nginx패키지를 얻게 된다. 

이런 문제를 해결하려면

 

RUN apt-get update && apt-get install -y 

이렇게 적으면 도커파일이 더 이상의 코딩이나 수동작업 없이 최신 패키지 버전을 설치 할 수 있다. 이것은 cache busting이라고 한다. 

RUN apt-get update && apt-get install -y \
    aufs-tools \
    automake \
    build-essential \
    curl \
    dpkg-sig \
    libcap-dev \
    libsqlite3-dev \
    mercurial \
    reprepro \
    ruby1.9.1 \
    ruby1.9.1-dev \
    s3cmd=1.1.* \
 && rm -rf /var/lib/apt/lists/*

위에 예제는 적절하게 권장사항을 잘 수행한 예시이다. s3cmd는 1.1 버전을 사용을 하도록했다 이미지가 만약 이전 버전을 사용하고 새로운 버전을 지정시키면 apt-get update에 캐시 버스팅을 하고 새로운 버진을 설치한다.  /var/lib/apt/lists를 제거하여 캐시를 적절히 정리하면 캐시가 레이어에 저장되지 않기 때문에 이미지 용량을 줄일 수 있다. RUN 구문은 apt-get update와 함께 시작하므로, 패키지 캐시는 항상 apt-get install 전에 정리될 것이다.

 

9. CMD

컨테이너가 실행될 때 실행할 명령을 지정한다. cmd는 한 번만 사용할 수 있으며, 마지막으로 지정된 cmd 지시자가 적용.

CMD 명령

여기서 명령은 컨테이너 내부에서 실행할 쉘 명령 또는 실행 파일이다. 명령은 배열로 지정되며, 첫 번째요소는 실행할 프로세스 또는 실행 파일의 경로이고 나머지 요소는 해당 프로세스 또는 시행 파일에 전달되는 인수이다. 

 

10. ENTRYPOINT

docker 컨테이너가 시작될때 실행되는 기본 실행 파일 또는 명령을 지정 하는 것이다. 

ENTRYPOINT 명령

여기서 명령은 컨테이너 내부에서 실행할 실행 파일 또는 쉘 명령이다. 명령은 배열 형태로 지정되며 첫 번째 요소는 실행할 프로세스 또는 파일의 경로이고 나머지 요소는 해당 프로세스 또는 파일에 전달되는 인수이다. 

 

여기서 궁금한게 있는데 그럼 CMD랑 차이가 뭔가를 생각을 했다. 

만약에 두개 다 쓰면 

FROM ubuntu:latest

RUN apt-get update
RUN apt-get install -y python3

COPY app.py /app.py

ENTRYPOINT ["python3"]
CMD ["/app.py"]

이렇게 쓸 수 있을 것이다. 해석을 해보면 컨테이너가 실행될 때 /app.py 파일을 python3로 실행을 할 것이라는 것이다.

entrypoint는 컨테이너가 시작될 때 실행되는 기본 실행 파일을 지정하고 cmd는 entrypoint에 전달되는 인수로 된다.  

 

FROM ubuntu:latest

RUN apt-get update
RUN apt-get install -y python3

COPY app.py /app.py

CMD ["python3", "/app.py"]

근데 이렇게 써도 위에랑 비슷한 결과를 나온다.  ["python3", "/app.py"]로 설정되어 있어 컨테이너가 시작될 때 /app.py를 실행하는 Python 3 명령이 실행됩니다. 근데 두개 다 쓰는 이유는 ENTRYPOINT를 사용하면 컨테이너 실행 명령에 인수를 추가하기 용이하거나, 실행 명령의 수정이 필요한 경우에 유용하기 때문이다. 

 

11. VOLUME

컨테이너와 호스트 머신 간 데이터를 공유하기 위한 방법이다. 컨테이너 내부의 특정 경로와 호스트 머신의 경로를 연결하여 데이터를 영구적으로 저장하고 공유하는 역활을 한다. 이것을 사용하면 컨테이너가 종료되거나 삭제되더라도 데어터가 유지되며, 여러 컨테이너 간에 데이터를 공유할 수 있다. 

FROM my_image

VOLUME /path/in/container

/path/in/container은 컨테이나 내부 경로로 컨테이너 내부에서 데이터가 저장되는 위치를 지정하는 것이다 .

 

배운 내용을 바탕으로 한번 dockerfile을 작성을 했다. 

#기본이 되는 이미지 보통 os를 적는다 ubuntu쓰고 버전을 같이 쓴다 .
FROM ubuntu:20.04 

#이미지에 메타데이터를 추가하는 것..예를 들면 이미지 버전, 제작자 , 도커파일 설명을 예로 들수있다. 

#작성자
LABEL maintationer ="han john< hanjeonghun@gmail.com >"
#설명
LABEL description="This is a sample Dockefile"

#경로
WORKDIR /app

COPY app.py .
COPY requirements.txt .

#/app/경로에 app.py를 복사
ADD app.py /app/

#포트번호
EXPOSE 3300

#환경변수 
ENV MY_VARIABLE=my_value
ENV DATABASE_HOST=localhost DATABASE_PORT=5432

#명령
RUN apt-get update && apt-get install -y \
aufs-tools \
curl \
&& rm -rf /var/lib/apt/list/*

ENTRYPOINT [ "python3" ]
CMD [ "/app.py" ]

 

dockerfile을 이용해 image 빌드 시키기 

docker build -t first-image .

 

image 빌드가 잘 됬는지 확인 

docker images

 

docker desktop에서 확인 

 

 

Dockerfile에 지정한 값과 이미지들이 잘 들어갔걸 알 수 있다.

 

 

 

- 참고 -

https://yceffort.kr/2022/02/dockerfile-instructions 

반응형