[Docker] Dockerfile 작성 및 사용법 요약
Dockerfile 작성 및 사용법 요약
FROM
FROM
을 사용하여 base image를 지정한다
주로 ubuntu 같은 OS를 지정하게 된다
Base image를 지정할때는 ubuntu:18.04 처럼 OS와 버젼까지 정확히 지정해주는것이 좋다
FROM ubuntu:18.04
RUN
package를 인스톨 한다든지 등등의 shell command를 해당 docker image에 실행시킬때 사용한다
예를 들어, 해당 docker image에 nginx를 설치하고 싶다고 한다면 아래와 같이 Dockerfile에 명시하면 된다
RUN ["apt-get", "install", "-y", "nginx"]
RUN
은 bin/sh -c
command 통해서 주어진 커맨드들을 실행시킨다
그러므로 만일 shell이 없는 platform에서 커맨드를 실행시켜야 한다면 exec
를 사용해야 한다
EXPOSE
Docker container 외부에 노출할 포트를 지정할때 사용된다
예를 들어 port 8080을 노출하고 싶다면 아래와 같이 명시하면 된다
EXPOSE 8080
참고로, 한개 이상의 port를 노출시켜줄수 있다
조심해야 할 점은, EXPOSE
을 지정해주었다고 해서 곧바로 그 포트를 외부에서 접속할수는 없다는 것이다
보안상 이유 때문에 docker는 포트를 자동으로 open 하지는 않는다
Docker container를 실행할때 EXPOSE
를 통해서 지정된 포트를 열어주어야 한다
ENV
Environment variable을 지정할때 ENV
을 사용하면 된다ENV
로 지정한 환경변수 는 $variable_name
이나 ${variable_name}
으로 사용될 수 있다
FROM busybox
ENV FOO /bar
WORKDIR ${FOO} # WORKDIR /bar
ADD . $FOO # ADD . /bar
COPY \$FOO /quux # COPY $FOO /quux
${variable_name}
syntax를 사용하면 아래와 같은 옵션도 가능하다:
${variable:-word}
:variable
이 만일 정의가 안되어 있으면word
부분의 값이 사용된다.${variable:+word}
: 위에와 밴다의 경우다.variable
이 정의가 되어있으면word
부분의 값이 사용된다. 정의가 안되어 있으면 empty string으로 지정된다.
ENV
으로 지정된 환경변수는 docker image를 실행 시킬때 -e
옵션을 사용해서 override 할 수 있다
docker run -e FOO='/something-else' test
CMD
CMD
를 사용하여 docker container가 시작할때 실행할 커맨드를 지정할수 있다RUN
과 기능은 비슷하지만 차이점은 CMD
는 docker image를 빌드할때 실행되는 것이 아니라 docker container가 시작될때 실행된다는 것이다
주로 docker image로 빌드된 application을 실행할때 쓰인다
CMD ["python", "main.py"]
참고로 CMD
으로 지정된 커맨드들은 docker run
커맨드로 실행시킬때 override 할 수 있다
그러므로 Dockerfile 에서는 CMD
로 디폴트 커맨드를 지정하고 실제 docker run
커맨드를 실행시킬때는 다른 적절한 커맨드를 줄 수 있다
ENTRYPOINT
Docker image가 실행될 때 실행되어야할 기본 command를 지정한다CMD
와 비슷하지만 CMD
는 override 가 가능하지만 ENTRYPOINT
는 override 할 수 없다
대신에 docker run
커맨드로 추가하는 커맨드 들은 ENTRYPOINT
에 지정된 커맨드에 옵션으로 추가된다
ENTRYPOINT ["/usr/sbin/nginx"]
...
docker run -t -i test/test:v1 -g "daemon off"
위의 경우 /usr/sbin/nginx -g "daemon off"
커맨드가 실행된다
CMD
와 ENTRYPOINT
를 혼합해서 사용할 수 도 있다CMD
로 지정된 옵션은 만일 docekr run
커맨드로 아무런 커맨드가 추가되지 않으면 default로 추가된다
ENTRYPOINT ["/usr/sbin/nginx"]
CMD ["-h"]
...
docker run -t -i test/test:v1 -g "daemon off" # « nginx -g "daemon off" 실행
docker run -t -t test/test:v1 # « nginx -h 실행
만약 정말로 ENTRYPOINT
으로 지정된 커맨드를 override 해야 한다면 --entrypoint
옵션을 사용해서 할 수 있다
WORKDIR
Working directory를 지정해준다
Linux의 cd
커맨드의 개념으로 생각하면 된다. WORKDIR
마저도 override 할 수 있다-w
옵션을 사용하면 된다
USER
해당 docker image
를 실행할 user 를 지정 해준다
USER nginx
위의 대로 지정하면 docker image가 실행될때 docker container에서 nginx 유저로 image를 실행하게 된다
유저 이름 뿐만이 아니라 UID 나 GID를 사용할 수 도 있다
USER user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER uid:group
Runtime 때 override 하고 싶으면 -u
옵션을 사용하면 된다USER
으로 지정하지 않으면 default로 root 유저로 image가 실행된다
VOLUME
VOLUME
을 사용하여 호스트의 directory를 docker 컨테이너에 연결시킬수 있다
그리하여 데이터, 소스코드, 외부설정파일 등등을 docker image에 commit 하지 않고 docker container에서 사용 가능 하도록 한다
주로 로그 수집이나 data 저장에 쓰인다
VOLUME ["/opt/project"]
ADD
파일과 디렉토리를 호스트에서 docker image로 copy한다.
ADD file /some/dir/file
만일 ADD
할려고 하는 디렉토리가 image에 존재하고 있지 않으면 docker가 자동으로 생성한다
생성된 directory는 0755 mode와 0 UID & GID로 생성된다
파일 소스는 파일 이름 과 directory 이외에도 URL이 될수도 있다
Directory를 ADD
하기 위해서는 /
로 끝나야 한다
주의할점은 빌드 directory 외부의 파일은 ADD
할 수 없다
만일 ADD
할려고 하는 파일이 tar
압축파일 이면 docker가 자동으로 압축을 풀어서 ADD
한다
한가지 더 주의할 점은, ADD
할려고 하는 파일이나 디렉토리와 같은 이름의 파일이나 디렉토리가 벌써 image 상에 존재 한다면 덮어 씌우지 않는다
COPY
ADD
와 기본적으로 동일하나 차이점은 URL을 지정할수 없고 압축파일을 자동으로 풀어주지 않는다
다시한번 강조할 점은, COPY
도 ADD
와 마찬가지로 빌드 디렉토리 밖의 파일들은 COPY
할 수 없다
그 이유는, COPY
(혹은 ADD
) 가 호스트에서 이루어지는것이 아니라
현재 빌드 디렉토리 자체가 Docker daemon에 upload 된 후 거기서 이루어지기 때문이다
LABEL
이름 그대로 label 을 생성한다
LABEL version="1.0"
LABEL location="SEOUL, KOREA" type="AWESOME"
docker inspect
커맨드를 통해 label들을 확인 할 수 있다.
ARG
docker build
커맨드로 docker image
를 빌드할때 설정 할 수 있는 옵션 들을 지정해준다
ARG env
ARG log_level=debug
위의 경우 docker build
커맨드로 빌드할때 --build-arg
옵션을 사용하여 env 와 log_level 값을 설정 해줄수 있다
docker build --build-arg env=prod -t test/test:v1 .
Secrete key나 계정 비밀번호 같은 민감한 정보는 이러한 방식으로 지정하지 않는걸 권한다
이렇게 지정하면 image에 그대로 남아있기 때문에 image가 노출되면 정보 또한 노출될수 있다
SHELL
디포트로 지정되어 있는 shell 타입을 바꿀수 있게 해준다. Linux의 default shell은 ["/bin/sh", "-c"]
이다
Building Docker Image
docker build
command를 사용해서 image를 빌드 하도록 한다
docker build -t "test/test:v1" .
ONBUILD
해당 image가 만일 다른 이미지의 base image로 쓰이는 경우 실행될 커맨드들을 지정할 수 있다
-t
옵션을 사용해서 빌드된 이미지의 repository와 이름 그리고 tag도 지정해줄수 있다
만일 tag를 지정해주지 않으면 디포트로 latest로 tag된다Docker image를 빌드할때 로컬 소스 뿐만이 아니라 github url를 지정해줄수도 있다
docker build -t "test/test:v1" github.com/test/docker-test
Github url을 지정해주는 경우 해당 github url에 Dockerfile이 존재해야 한다
-f
옵션을 사용하면 Dockerfile 경로를 지정해 줄수 있다- 파일 이름이 Dockerfile이 아니거나 Dockerfile의 위치가 다른 곳에 위치해 있을때 사용 하면 된다
docker build -t "test/test:v1" -f /path/to/file
.dockerignore
파일을 사용하여 docker 이미지에 포함되면 안되는 파일들을 명시할수 있다 (.gitignore
과 같은 기능이라고 생각하면 된다)
Debugging Docker Image Build
docker build
커맨드를 사용하여 Dockerfile을 실행시키면 각각의 instruction가 실행될 때 마다 이미지ID가 생성된다(예를 들어 22d47c8cva9)
위에서 언급 했듯이 각각의 instruction 자체가 파일시스템 즉 이미지를 생성시키는 것이므로 이미지ID가 생성이 되는 것이다
그러므로 만일 docker image 빌드가 도중에 실패하게 되면 마지막으로 실행된 instruction의 ID를 가지고 docker run
커맨드를 실행시켜 그 상테의 docker 이미지를 실행시킬수 있다
그래서 shell 접속을 해서 실패한 Dockerfile instruction을 실행시켜서 디버깅을 할 수 있다.
docker run -t -i 22d47c8cva9 /bin/bash
- Docker image를 빌드할때 이미 실행된 instruction들은 docker가 cache처럼 유지하고 있는다
그래서 변경사항이 없다면 이미 실행된 instruction들은 다시 실행시키지 않고 이미 만들어진 파일시스템 / 이미지 부터 빌드를 시작을 한다
그러므로 변경사항이 있는 부분만 빌드를 함으로 효율적으로 빌드를 할 수 있는 것 이다
만일 cache된 layer를 사용하지 않고 새로 실행하고 싶다면 (예를 들어 apt-get update
커맨드 같은 경우) --no-cache
옵션을 docker build
커맨드에 추가해서 실행하면 된다
docker build --no-cache -t="test/test:v1" .
docker history
를 사용하여 docker image가 빌드된 스텝들을 볼 수 있다.
Deleting a Docker Image
docker rmi
커맨드를 사용하여 docker image를 지울수 있다.
docker rmi test/test:v1
Running Docker Container
docker run
커맨드를 사용해서 docker container를 실행시킨다-d
옵션을 설정함으로서 docker container가 background detache되어 실해외도록 한다
멈추지 않고 계속해서 실행되야 하는, 즉 대부분의 production application, docker image들은 이 옵션을 설정하도록 한다-p
옵션으로 호스트의 포트와 docker container가 expose한 포트를 mapping 한다
설정 하지 않으면 호스트의 랜덤한 포트값이 지정된다
예를 들어 docker container의 포트 80을 로컬 호스트 포트 80에 맵핑 하기 위해서는 아래와 같이 실행하면 된다
docker run -d -p 80:80 -name test "test/test:v1"
UDP port를 지정하기 위해서는 /udp
suffix를 붙혀주면 된다.
-P
옵션을 사용하면EXPOSE
로 지정한 모든 포트를 호스트의 랜덤 포트로 mapping 해준다- 이 옵션은 base image에서
EXPOSE
한 포트도 전부 맵핑 해준다
Docker 이미지, 컨테이너, 볼륨, 네트워크등 환경정리 prune
docker container prune
중지된 모든 컨테이너를 삭제한다
docker container prune
docker image prune
이름 없는 모든 이미지를 삭제한다
docker image prune
docker network prune
사용되지 않는 도커 네트워크를 모두 삭제한다
docker network prune
docker volume prune
도커 컨테이너에서 사용하지 않는 모든 도커 볼륨을 삭제한다
docker volume prune
docker system prune -a
중지된 모든 컨테이너, 사용되지 않은 모든 네트워크, 하나 이상의 컨테이너에서 사용되지 않는 모든 이미지를 삭제한다
따라서 남아있는 컨테이너 또는 이미지는 현재 실행 중인 컨테이너에서 필요하다
docker system prune -a