ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Docker] Dockerfile
    Docker 2019. 4. 4. 13:06

     

    Dockerfile은 COMMAND-VALUE 쌍으로 구성된 지시어로 이루어진 도커 이미지 설정 파일이다.

     

    베이스 이미지를 지정하고, 컨테이너에서 실행되는 명령을 정의하고, 환경 변수를 설정하고, 컨테이너에서 실행되는 데몬을 지정할 수 있다.

    Dockerfile에서 파일 시스템에 변경을 가하는 각 지시어는 베이스 이미지의 이미지 레이어의 상위 레이어가 생성되어 변경사항이 적용된다.

     

    FROM


    FROM 지시어로 베이스 이미지를 지정하여 레이어를 생성한다.

    지정된 이미지가 도커 호스트로 자동으로 풀다운된다.

    도커 호스트 또는 Docker Registry(DockerHub, Private Docker Registry, ..)에 있는 이미지만 지정이 가능하다.

     

    아래 세가지 형식으로 사용된다.

    FROM IMAGE
    FROM IMAGE:TAG
    FROM IMAGE@DIGEST

     

    RUN


    베이스 이미지를 기반으로 패키지를 설치하거나 환경을 구성할 때 사용한다.

    두가지 사용 형식이 있지만, 결과적으로 큰 차이는 없다.

     

    쉘 명령

    /bin/sh -c 으로 실행하는 것과 동일하게 작동한다.

    RUN yum -y install httpd

    자동으로 /bin/sh -c yum -y install httpd 로 변환된다.

     

    Exec 명령

    쉘을 거치지 않고 바로 실행한다. 따라서 환경 변수를 입력할 수 없고, JSON 형식으로 입력해야 한다.

    RUN [ "/bin/bash", "-c", "yum -y install httpd" ]

     

    CMD


    빌드한 이미지로부터 컨테이너가 실행될 때 특정 프로세스나 데몬을 실행하기 위해 사용한다.

    CMD 지시어를 여러번 사용할 경우, 마지막 지시어만 적용되므로 한번만 사용해야 한다.

    RUN과 마찬가지로 쉘 명령Exec 명령 두가지 형식으로 사용할 수 있다.

     

    FROM centos
    RUN yum -y install httpd
    CMD /usr/sbin/httpd -D FOREGROUND
    $ docker build -t centos:cmd .
    
    $ docker inspect centos-web:cmd
    [
        {
            ...
            "ContainerConfig": {
                ...
                "Cmd": [
                    "/bin/sh",
                    "-c",
                    "#(nop) ",
                    "CMD [\"/bin/sh\" \"-c\" \"/usr/sbin/httpd -D FOREGROUND\"]"
                ],
                "Entrypoint": null
            },
            "Config": {
                ...
                "Cmd": [
                    "/bin/sh",
                    "-c",
                    "/usr/sbin/httpd -D FOREGROUND"
                ],
                "Entrypoint": null
            }
            ...

     

    만일 docker run 시 명령어를 지정하면 CMD는 무시되고 지정된 명령어가 수행된다.

     

    ENTRYPOINT


    빌드한 이미지로부터 컨테이너가 실행될 때 특정 프로세스나 데몬을 실행하기 위해 사용한다.

    docker run 명령을 실행할 때 실행되므로 CMD 지시어보다 우선순위가 높다. 

     

    RUN 지시어와 동일하게 쉘 명령Exec  명령 두가지 형식으로 사용할 수 있다.

     

    ./Dockerfile
    
    FROM centos:latest
    RUN yum -y install httpd
    ENTRYPOINT /usr/sbin/httpd -D FOREGROUND
    $ docker build -t centos:entrypoint .
    
    $ docker inspect centos-web:entrypoint
    [
        {
            ...
            "ContainerConfig": {
                ...
                "Cmd": [
                    "/bin/sh",
                    "-c",
                    "#(nop) ",
                    "ENTRYPOINT [\"/bin/sh\" \"-c\" \"/usr/sbin/httpd -D FOREGROUND\"]"
                ],
                "Entrypoint": [
                    "/bin/sh",
                    "-c",
                    "/usr/sbin/httpd -D FOREGROUND"
                ]
            },
            "Config": {
                ...
                "Cmd": null,
                "Entrypoint": [
                    "/bin/sh",
                    "-c",
                    "/usr/sbin/httpd -D FOREGROUND"
                ]
            },
            ...

    Entrypoint 설정이 추가된 것을 확인할 수 있다. 

     

    CMD 지시어와는 달리 docker run 시 지정한 명령어는 무시되고 ENTRYPOINT 지시어가 실행된다. 쉘로 접속하려면 docker exec 명령을 사용해야 한다.

     

    mysql 이미지의 경우 ENTRYPOINT docker-entrypoint.sh 지시어가 포함되어있다. 이 스크립트에서 특정 환경변수를 검사하여 컨테이너를 실행한다.

    ONBUILD


    베이스 이미지를 생성할 때 사용하는 지시어로서, 이미지를 빌드한 후 해당 이미지를 기반으로 다른 이미지를 빌드할 때 적용되는 지시어다.

     

    ONBUILD 명령어가 적용된 이미지로 컨테이너를 생성해도 컨테이너는 해당 명령어를 실행하지 않는다. 해당 이미지를 베이스 이미지로 해서 다른 이미지를 빌드할때 명령어가 실행된다. 

     

    ONBUILD ADD 명령어는 도커 호스트의 파일을 컨테이너의 특정 디렉토리에 적용할 때 사용한다.

    FROM centos
    RUN yum -y install httpd
    ONBUILD ADD index.html /var/www/html
    CMD /usr/sbin/httpd -D FOREGROUND
    

     

    이미지를 빌드한다. FROM 지시어로 생성된 centos 레이어와 RUN 지시어로 생성된 레이어 두개만 나타난다. ONBUILD로 지정된 ADD index.html /var/www/html 명령은 실행되지 않고, OnBuild 필드로 업데이트 된 것을 확인할 수 있다.

    $ docker build -t centos:pre-onbuild .
    
    $ docker inspect centos-web:pre-onbuild
    [
        {
            ...
            "ContainerConfig": {
                ...
                "Cmd": [
                    "/bin/sh",
                    "-c",
                    "#(nop) ",
                    "CMD [\"/bin/sh\" \"-c\" \"/usr/sbin/httpd -D FOREGROUND\"]"
                ],
                "OnBuild": [
                    "ADD index.html /var/www/html"
                ]
            },
            "Config": {
                ...
                "Cmd": [
                    "/bin/sh",
                    "-c",
                    "/usr/sbin/httpd -D FOREGROUND"
                ],
                "OnBuild": [
                    "ADD index.html /var/www/html"
                ]
            },
            "RootFS": {
                "Type": "layers",
                "Layers": [
                    "sha256:d69483a6face4499acb974449d1303591fcbb5cdce5420f36f8a6607bda11854",
                    "sha256:f58e0e778d84a914c02385be57b7f0247b181f37b299579dd4d2e2fac9d9fa07"
                ]
            },
            ...
        }
    ]
    

     

    OnBuild가 적용된 이미지를 기반으로 또 다른 이미지를 생성한다. 이때는 ONBUILD로 지정된 ADD 명령어가 수행되어야 하므로 도커 호스트에 index.html 파일이 존재하여야 한다. OnBuild 필드가 null로 생성되고, ADD index.html /var/www/html 지시어가 적용된 레이어가 추가되었기 때문에 총 3개의 레이어가 나타난다.

    FROM centos:pre-onbuild
    RUN echo Test
    CMD /usr/sbin/httpd -D FOREGROUND
    $ docker build -t centos-web:onbuild .
    
    $ docker inspect centos-web:onbuild
    [
        {
            ...
            "ContainerConfig": {
                ...
                "Cmd": [
                    "/bin/sh",
                    "-c",
                    "#(nop) ",
                    "CMD [\"/bin/sh\" \"-c\" \"/usr/sbin/httpd -D FOREGROUND\"]"
                ],
                "OnBuild": null,
                ...
            },
            "Config": {
                ...
                "Cmd": [
                    "/bin/sh",
                    "-c",
                    "/usr/sbin/httpd -D FOREGROUND"
                ],
                "OnBuild": null,
                ...
            },
            "RootFS": {
                "Type": "layers",
                "Layers": [
                    "sha256:d69483a6face4499acb974449d1303591fcbb5cdce5420f36f8a6607bda11854",
                    "sha256:f58e0e778d84a914c02385be57b7f0247b181f37b299579dd4d2e2fac9d9fa07",
                    "sha256:d44e7018ea29cc14dedaf309240f573ae182c7141827478b0ab806e99697d339"
                ]
            },
            ...
        }
    ]
    

     

    VOLUME


    도커 볼륨을 생성한다.

     

    VOLUME 지시어를 설정하면 해당 컨테이너 패스에 연결되는 디렉토리를 생성하고 마운트한다.

    FROM centos
    RUN mkdir -p /tmp/share
    VOLUME /tmp/share
    $ docker build -t centos:volume .
    
    $ docker inspect centos:volume
    [
        {
            ...
            "ContainerConfig": {
                ...
                "Volumes": {
                    "/tmp/share": {}
                }
            },
            "Config": {
                ...
                "Volumes": {
                    "/tmp/share": {}
                }
            },
            ...
        }
    ]
    

     

    생성된 이미지로 컨테이너를 실행한다.

    $ docker run -itd --name centos-volume centos:volume
    
    $ docker inspect centos-volume
    [
        {
            ...
            "Mounts": [
                {
                    "Type": "volume",
                    "Name": "8fadb85943d78e953a16e643bc6ae1e5733419c8f8bb2d178cd0d45ba39f5217",
                    "Source": "/var/lib/docker/volumes/8fadb85943d78e953a16e643bc6ae1e5733419c8f8bb2d178cd0d45ba39f5217/_data",
                    "Destination": "/tmp/share",
                    "Driver": "local",
                    "Mode": "",
                    "RW": true,
                    "Propagation": ""
                }
            ],
            "Config": {
                ...
                "Volumes": {
                    "/tmp/share": {}
                }
            },
            ...
        }
    ]
    

     

    도커 볼륨이 자동으로 생성된 것을 확인할 수 있다. 

    $ docker volume ls
    DRIVER              VOLUME NAME
    local               8fadb85943d78e953a16e643bc6ae1e5733419c8f8bb2d178cd0d45ba39f5217

     

     

    EXPOSE


    EXPOSE 지시어를 사용하여 컨테이너가 사용할 포트를 지정한다.

     

    컨테이너를 실행할 때 반드시 포트 매핑 설정을 넣어주어야 한다. 만일 호스트 네트워크 드라이버를 사용한다면 포트 매핑을 설정하지 않고, 자동으로 호스트 포트로 노출된다.

    FROM centos
    RUN yum -y install httpd
    RUN echo 'Hello Devaom!' > /var/www/html/index.html
    CMD /usr/sbin/httpd -D FOREGROUND
    EXPOSE 80
    $ docker build -t centos:expose .
    
    $ docker run -itd --name centos-expose -p 80:80 centos:expose

     

    이미지 정보에서 포트 노출을 확인할 수 있다.

    $ docker inspect centos:expose
    [
        {
            ...
            "ContainerConfig": {
                ...
                "ExposedPorts": {
                    "80/tcp": {}
                },
                ...
            },
            "Config": {
                ...
                "ExposedPorts": {
                    "80/tcp": {}
                },
                ...
            },
            ...

     

    docker run 시 포트 매핑 옵션을 적용하여 호스트에서 해당 포트가 LISTEN 상태임을 확인할 수 있어야 한다.

    $ netstat -nltp
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    ...
    tcp6       0      0 :::80                   :::*                    LISTEN      -                   

     

    MAINTAINER


    MAINTAINER 지시어는 이미지의 관리자 정보를 기록한다.

    MAINTAINER Devaom

     

    이미지 정보를 조회하면 Author 필드에 추가된 것을 확인할 수 있다.

    [
        {
            ...
            "Author": "Devaom",
            ...

     

     

     

     

     

     

     

     

     

     

     

     

     

    'Docker' 카테고리의 다른 글

    [Docker] 자체 네트워크 드라이버  (0) 2019.04.08
    [Docker] 데이터 볼륨  (0) 2019.04.03
    [Docker] 이미지 아카이브  (1) 2019.04.02
    [Docker] 컨테이너의 구조  (1) 2019.04.02
Designed by Tistory.