도커 - Dockerfile, docker-compose!
Dockerfile
nginx서버 /usr/share/nginx/html/index.html 디렉토리에 index.html파일을 삽입하여 다시 이미지를 만들고 싶을때
이미 존재하는 nginx 서비스를 사용할때 다시 이미지화 할 수 있으면 좋지 않을까?
이미지 레이어를 사용해 효과적으로 이미지를 생성할 수있도록 스크립트를 제공하는데 Dockerfile이다.
다음과 같이 Dockerfile을 작성
1 | FROM nginx:latest |
index.html파일에<h1>Hello Docker!<h1>삽입!
docker build -t mywebserver ./
현재 디렉토리의 Dockfile을 사용해서 mywebserver란 이미지를 새성한다.
docker build -t 생성이미지이름:태그 Dockerfile위치
출력값
1 | Sending build context to Docker daemon 3.072kB |
mywebserver라는 이미지가 생성되었다, 기존의 nginx이미지를 사용해서!
주의: 도커파일의 이름 기본값은
Dockerfile이며 이를 변경하면 별도의 이름 지정 속성을 사용해야 한다.
Dokcerfile 명령어
도커파일은 docker이미지를 생성하기 위한 파일로 기존 이미지에 여러가지 설정을 붙여 새로운 이미지를 만들때 사용하는 파일이다.
| 명령어 | 설명 |
|---|---|
FROM |
가장 기본이 되는 이미지 지정, 필수 입력 항목 |
RUN |
커맨드 실행, 실행할 때 마다 새로운 레이어가 생성된다, 때문에 왠만한건 한줄처리로 해결하는 것이 좋다. RUN apt-get update && apt-get install -y curl nginx |
CMD |
docker run 명령인자 생략시에 실행되는 default 명령어 혹은 default 파라미터, 파라미터는 ENTRYPOINT 에서 사용된다. 한번만 입력 가능. |
ENTRYPOINT |
데몬 실행, docker run 시 실행되는 명령어, CMD 와 다르게 생략되지 않는다 |
ONBUILD |
빌드완료후 실행할 명령, 여기서 명령은 Dockerfile의 명령(ADD, COPY 등), ONBUILD를 통해 새로운 이미지 레이어가 생성되고 지정된 명령어를 수행한다. |
STOPSIGNAL |
컨테이너 종료시 송신하는 시그널 설정. 시그널번호(9), 시그널명(SIGKILL) 지정 가능 |
HEALTHCHECK |
컨테이너 안의 프로세스가 정상동작하는지 체크, ex: `HEALTHCHECK –interval=5m –timeout=3s CMD cur -f http://localhost/ |
ENV |
환경변수 지정, 공백이 표함될 경우 쌍따옴표 필수, 명령 사용마다 레이어가 늘어남으로 \ 로 계행하여 한줄로 사용하는 것이 효율적. docker run --env 로 기본값 대체 가능 |
ARG |
Dockerfile 안의 환경변수, ENV 와는 달리 Dokcerfile 안에서만 사용 가능. docker run --build-arg 로 기본값 대체 가능 |
WORKDIR |
작업 디렉터리 지정, 여러번 사용해 디렉토리 지정이 가능하며 상대 경로 입력해 현 경로에서 이동함. |
LABEL |
라벨 지정, key value 형식의 각종 코멘트(작성자, 버전 등) 지정 |
EXPOSE |
공개 포트번호 지정, ex: EXPOSE 8080 |
ADD |
파일 및 디렉토리 추가, ADD <호스트 파일경로> <Docker이미지 파일경로>, 호스트 파일 경로는 HTTP URL 가능. *, ? 기호 사용하여 파일 이름 형식 지정 가능.WORKDIR 과 상대경로로 디렉터리 지정, 호스트 파일경로를 URL 로 사용시 마지막 디텍토리 슬래시 / 를 제거해 파일명 지정 가능, 제거하지 않을경우 URL로 파일명 지정.tar, gzip 등의 압축은 자동으로 해제됨, 단 URL의 경우 풀리지 않음. .dockerignore 을 통해 특정 파일 제외 가능 |
COPY |
파일 및 디렉토리 추가, ADD 가 더 많은 기능을 포함하고 있다. 단순 로컬 파일을 이미지로 전달하고 싶을땐는 COPY 를 사용. |
USER |
RUN, CMD, ENTRYPOINT 실행 사용자 지정. ex: USER [username/UID] |
SHELL |
기본 쉘 설정. ex: SHELL ["/bin/sh", "-c"] |
VOLUME |
볼륨 마운트 ex: VOLUME ["/data/log", "/var/log"], 인자를 하나만 사용할 경우 호스트와 컨테이너 모두 해당 디렉토리를 사용. |
MAINTAINER |
작성자 지정 |
RUN, CMD, ENTRYPOINT차이점: https://blog.leocat.kr/notes/2017/01/08/docker-run-vs-cmd-vs-entrypoint
RUN - 새로운 레이어에서 명령어를 실행하고, 새로운 이미지를 생성한다. 보통 패키지 설치 등에 사용된다. e.g. apt-get
CMD - default 명령/파라미터를 설정한다. docker run 실행 시 실행 커맨드를 주지 않으면 이 default 명령이 실행된다. 실행 커맨드 입력 CMD 설정은 생략된다.
ENTRYPOINT - CMD 와 차이점은 실행 커맨드 입력시에도 생략되지 않는것. 아래와 같은 설정이 가능하다.
1 | FROM ubuntu:16.04 |
해당 Dockerfile 로 sample 이란 이미지를 생성 후 아래처럼 사용 가능
1 | docker run -it sample ## CMD 의 인자를 그대로 사용, 10초 간격 갱신 |
FROM만 필수항목이고 나머지는 모두 없어도 된다.
(나머지 속성은 모두 기본이미지에 살을 붙이는 속성)
FROM 명령만 적어 Dockerfile을 생성해보자.ubuntu 컨테이너에 nginx를 설치하고 index.html파일을 삽인한 후 다시 이미지화.
1 | ## Dockerfile.base |
docker images로 내가 지정한 이미지가 생성됬는지 확인하고 docker history 이미지명:태그명으로 Dockerfile을 실행하면서 어떤 명령들이 실행되었는지 확인가능하다.
1 | $ docker build -t ubuntunginx:1.0 -f Dockerfile.base . |
-f : Dockerfile 별도 이름 지정
생각해보면 docker hub에서 이미지 다운받아 컨테이너를 만들때 부터 어떤 포트가 들어갈지, 어떤 명령을 수행할지 이미 설정된 이미지들이 있는데 모두 Dockerfile로 만들어진 이미지들이다.
union file system
위의 출력값을 통해 도커는 union file system을 사용함을 알 수 있다.
계층화된 파일 시스템을 사용해 중복 데이터를 피해 효율적인 이미지 관리를 할 수 있다.
(시간 단축, 데이터 효율!)
docker images로 확인해 보면 기존에 생성했던 ningx 이미지를 사용해 새로만든 mywebserver의 이미지를 생성한다.
1 | REPOSITORY TAG IMAGE ID CREATED SIZE |
1 | docker run --name newNginx -d -p 80:80 mywebserver |
위 명령어로 해당 이미지를 실행시키고 위에서 정의한 index.html 파일이 /usr/share/nginx/html 디렉터리에 들어있는지 확인
docker image inspect로 nginx:latest 이미지와 mywebserver 이미지를 확인하면
1 | // nginx:latest |
1 | // mywebserver |
MergedDir, UpperDir, WorkDir은 도커 이미지 구축을 위한 데이터로
두 이미지의 내용이 일치하는 부분이 상당히 많다.
arm docker build
apple silicon 에서 docker build 시 각별한 주의가 필요하다.
apple silicon 에서 빌드한 이미지는 arm 시스템에서 동작하는 Docker 이미지가 생성되고
일반 amd CPU 를 사용하는 시스템에서 해당 이미지를 실행하면 아래와 같은 오류가 발생한다.
exec format error
빌드시 아래와 같이 amd 아키텍처에서 실행할 것임을 명시해야한다.
1 | docker build --platform linux/amd64 -t docker-test . |
not certified ssl 등록
공식 Docker Registry 가 아닌 사설 SSL 인증서가 적용된 Private Registry 지정시 아래와 같은 오류가 발생할 수 있다.https 를 사용하더라도 공식 SSL 인증서가 아니라면 아래 에러가 docker login, pull, push 할 때 마다 발생한다.
1 | "SSL certificate problem: self signed certificate in certificate chain" |
아래 파일에서 insecure-registries 속성을 추가해서 해결 가능하다.
- ubuntu:
/etc/docker/daemon.json - mac:
/Users/{username}/.docker/daemon.json
1 | { |
멀티스테이지 빌드(Multi-Stage Build)
Spring Boot 서버를 실행하는 Docker 이미지를 만드려면 jar 파일을 COPY 하여 실행시키는 Dockerfile 을 작성한다.
jar 파일을 만들기 위해 host 에는 JDK 가 설치되어 있어야 하는데, jar 를 만드는 과정까지 Docker 컨테이너에서 수행할 수 있다.
1 | # 빌드 단계 |
--no-daemon 옵션은 Gradle 빌드 실행 시 Gradle daemon 프로세스를 사용하지 않도록 하는 옵션.
Gradle 데몬은 빌드 속도를 높이기 위해 백그라운드에서 상시 실행되며, 이전 빌드 결과를 캐싱하여 다음 빌드를 빠르게 시작할 수 있도록 하지만 Docker나 CI/CD 환경에서는 데몬이 계속 실행되면 자원 관리나 프로세스 종료 문제 등이 발생할 수 있기 때문에, –no-daemon 옵션을 사용하여 빌드가 완료되면 프로세스가 종료되도록 하는 것이 좋음.
docker-compose
지금까지 도커와의 링크를 위해 네트워크, 볼륨, 혹은 --link 속성으로 컨테이너간의 연결을 진행하였는데docker-compose 혹은 dockerfile을 사용하면 복잡한 명령어를 파일단위로 관리할 수 있다.
docker-compose는 일종의 툴로 docker-compose.yaml 파일을 사용해 여러개의 컨테이너를 한번에 생성할 수 있다.
Dockerfile 로 이미지를 생성하고docker-compose 로 생성한 이미지를 컨테이너화 시킨다.
컨테이너화 할때 사양한 설정 명령을 삭성해야 하며 docker run 명령이 10줄이 넘어갈 수 있다.docker-compose는 단순 명령 실행의 떨어지는 가독성을 보완하고 1개의 컨테이너만 생성하는 것이 아니라 여러개의 컨테이너를 연관지어 한꺼번에 생성 가능하게해준다.
docker compose 설치 및 운영
apt-get install로 설치가능하지만 버전에 따른 오류가 많기에 아래 명령으로 실행
위 사이트에서 docker가 제공해준 실행파일을 다운 받은 후 권한을 설정한다.
1 | sudo curl -L https://github.com/docker/compose/releases/download/1.21.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose |
그후 vi로 docker-compose.yml파일 생성
샘플로 wordpress, mysqlDB 서비스를 생성해보자.
1 | version: '2' |
docker-compose up명령으로 docker-compose.yml파일 실행
1 | docker-compose up |
실행과 동시에 출력되는 로그가 계속 뜨는데 도중에 나갈 수 없다.
시작할때 백그라운드로 실행해야 한다.
$ docker-compose up -d : 백그라운드로 실행
묶음으로 실행되기 때문에 해당 컨테이너들끼리 사용하는 브릿지 네트워크가 자동으로 생기는데 파일이 존재하는 디렉터리 명으로 생성된다.kouzie 홈디렉토리에서 docker-compose.yml을 생성해 실행했기 때문에 kouzie_default 라는 브릿지 네트워크가 생겼다.
그리고 컨테이너 명도 별도로 지정하지않아 db와 wordpress앞에 디렉터리명이 붙어 생성된다.
1 | $ docker ps |
이번엔 redis와 파이썬 웹서버를 묶어사용하는 docker-compose.yml을 생성
1 | version: '3.3' |
webserver의 경우 build: . 이 적혀있는데 이는 같은 디렉토리에 있는 Dockerfile을 빌드해서 생성한 컨테이너를 사용하겠다는 뜻.
1 | ## Base Image |
Dockerfile에는 각종 파일을 복사하고 app.py코드르 실행하는 스크립트가 작성되어있다.
docker-compose up 실행, 실행하는 주소로 접속해보면 그림처럼 출력된다.
{: .shadow}
docker-compose 상태 확인
docker-compose ps 명령으로 컨테이너 동작 상황을 알 수 있다.
단 docker-compose.yml파일이 있는 위치에서 실행해야한다.
1 | $ docker-compose ps |
그 외에도 각종 명령어 들이 존재
docker-compose port webserver 80 (80번포트가 어떤 외부포트와 매핑되어있는지 출력)docker-compose config (docker-compose.yml파일 안의 정보 출력)docker-compose kill -s SIGINT (kill -s 9 하면 서버를 종료시킨다)docker-compose rm (컨테이너 삭제)docker-compose down (kill -s 9 and rm)
down후에 ps로 한번 모든 컨테이너가 종료되었는지 확인해보자.
docker-compose 앵커
yaml 설정 중복을 줄이고 설정을 재사용하기 위해 사용
1 | # 앵커이름 및 내부에 사용할 yaml 설정 지정 |
병합 키(<<) 문법을 사용하여 속성명부터 재활용할 수 있다.
1 | x-test-logging: |
docker-compose 환경변수
docker 컨테이너 생성시 환경변수를 -e 옵션으로 지정할 수 도 있지만 --env-file 을 사용해 설정할 수 도 있다.
1 | docker run --env-file .env <이미지 이름> |
docker-compose 에서는 .env 숨김파일을 docker-compose.yml 과 같은 위치에 지정해놓을 경우 docker-compose up 명령실행시 자동으로 환경변수 파일이 지정된다.
아래와 같이 .env 파일을 생성하고
1 | GRAFANA_ADMIN_USER=admin |
environment 속성에 환경변수 사용하도록 이름 지정
1 | services: |
환경별로 다르게 설정하고 싶다면 .env 를 삭제하고 아래처럼 명시하여 실행 가능.
1 | docker-compose --env-file dev.env up -d |
혹은 아래와 같이 environment 에 들어가 환경변수를 직접 env 파일에 명시할 수 있다.
1 | # dev.env |
1 | grafana: |