Docker
Introduction
- 가장 짧게 요약을 하자면 가상의 환경에서 미리 정해져있는 필요한 프로그램들의 리스트를 통째로 설치하고 실행한 뒤 가상의 환경을 종료시킴으로써 내 컴퓨터는 깔끔하게 아무 영향을 받지 않도록 해주는 녀석입니다.
Concept
- Image, Docker engine, Container
- docker engine는 image를 통해 container라는 실행 객체를 생성하고 실행
구성요소
- Docker Client : 도커를 구성하고 운영 관리하는 패키지로 주로 관리자가 가장 많이 사용한다. docker cli 가 여기에 해당
- Docker Server : 도커를 실행하는 데몬이 동작하는 서버
- 내부에는 이미지를 담아둘수 있는 볼륨이 필요하고, 해당 이미지는 내부 또는 외부의 repository 사용
- 서버는 운영체제가 동작하고, 운영체제에서는 컨테이너 서비스를 제공하고 있어야 한다.
- 도커 데몬이 동작해야 한다.
- 이미지 : 이미지는 로컬 또는 Docker Hb등과 같은 퍼블릭 Repository를 사용할수 있다.
CentOS Docker 설치
-
리눅스 환경에서는 각 배포판에서 제공하는 패키지 관리자를 사용해서 도커를 설치할 수 있습니다. 단, 일반적으로 패키지 관리자는 보수적으로 관리되기 때문에 최신 버전을 설치하고자 한다면 도커에서 제공하는 스크립트를 사용해서 설치하는 것이 좋습니다. 여기서는 이 스크립트를 사용해 정식 릴리즈된 도커 최신 버전을 설치해보겠습니다.*
-
curl이 없다면 sudo apt-get curl로 설치합니다.
-
$ curl -s https://get.docker.com sudo sh - 아래 일부 건더 뜀
-
- yum-config-manager 유틸리티를 제공하는 yum-utils를 설치하십시오
- yum install -y yum-utils
- 안정적인 저장소를 설정
- yum-config-manager –add-repo https://download.docker.com/linux/centos/docker-ce.repo
-
docker-ce를 설치
- yum install -y docker-ce repo
-
옵션 : 에지 저장소 (최신버전)으로 설정(활성화/비활성화)
- sudo yum-config-manager –enable docker-ce-edge
- sudo yum-config-manager –enable docker-ce-testing
- sudo yum-config-manager –disable docker-ce-edge
-
옵션 : docker-ce 특정 버전 설치
- yum install docker-ce-17.03.0.ce
- systemctl 을 통해 서비스 구동 및 등록
- sudo systemctl start docker
- sudo systemctl enable docker
- 이미지 시작
- docker run hello-world
- 이미지가 없으면 Repo에서 Pull하고 실행까지 수행
docker 이미지와 컨테이너 삭제 방법
- docker ps : 동작중인 컨테이너 확인
- docker ps -a : 정지된 컨테이너 확인
- dockeer rm [컨테이너id] : 컨테이너 삭제
- docker rm [컨테이너id], [컨테이너id] : 복수개 삭제
-
docker rm
docker ps -a -q
: 컨테이너 모두 삭제 - docker images : 현재 이미지 확인
- docker rmi [이미지id] : 이미지 삭제
- docker rmi -f [이미지id] : 컨테이너, 이미지 동시 강제삭제
- docker system prune - a -f : 안쓰는 이미지와 컨테이너 삭제
docker 이미지 경로 바꾸기
$ vi /lib/systemd/system/docker.service
[Service]
...
#ExecStart=/usr/bin/dockerd -H fd://
ExecStart=/usr/bin/dockerd -g /DATA/docker -H fd://
$ sudo service docker stop
$ sudo systemctl daemon-reload
도커 데이터가 저장될 경로를 먼저 만들어주어야 한다.
mkdir /home/ykkim/docker
그런 다음 기존에 docker 경로를 위 경로로 통째로 복제해준다.
sudo rsync -aqxP /var/lib/docker /home/ykkim/docker
$ sudo service docker start
$ docker pull alpine:3.4 # 작은용량은 이미지를 다운받아 정상 동작을 확인
$ ls /원하는디렉토리
containers image network overlay plugins swarm tmp trust volumes
docker 명령어 https://docs.docker.com/engine/reference/run/
- 라이프사이클
- docker run 컨테이너를 생성한다.
- docker stop 컨테이너를 정지시킨다.
- docker start 컨테이너를 다시 실행시킨다.
- docker restart 컨테이너를 재가동한다.
- docker rm 컨테이너를 삭제한다.
- docker kill 컨테이너에게 SIGKILL을 보낸다. 이에 관련된 이슈가 있다..
- docker attach 실행중인 컨테이너에 접속한다. * docker wait 컨테이너가 멈출 때까지 블럭한다.
- docker images 모든 이미지 목록을 보여준다.
- docker build Dockerfile을 통해 이미지를 생성한다.
- docker commit 컨테이너에서 이미지를 생성한다.
- docker rmi 이미지를 삭제한다.
- docker insert URL에서 이미지로 파일을 집어넣는다. * docker load 표준 입력으로 tar 파일에서 (이미지와 태그를 포함한) 이미지를 불러온다.(0.7부터 사용가능).
- docker save 모든 부모 레이어와 태그, 버전 정보를 tar 형식으로 표준출력을 통해 @@@ (0.7부터 사용가능).
- 관련된 정보를 출력해주는 명령어
- docker ps 명령어는 실행중인 컨테이너 목록을 보여준다.
- docker inspect ip 주소를 포함한 특정 컨테이너에 대한 모든 정보를 보여준다.
- docker logs 컨테이너로부터 로그를 가져온다.
- docker events 컨테이너로부터 이벤트를 가져온다.
- docker port 컨테이너의 특정 포트가 어디로 연결되어있는지 보여준다.
- docker top 컨테이너에서 실행중인 프로세스를 보여준다.
- docker diff 컨테이너 파일 시스템에서 변경된 파일들을 보여준다.
- Import / Export
- docker cp 컨테이너 내의 파일을 호스트로 복사한다.
- docker export 컨테이너 파일 시스템을 tarball로 출력한다.
- docker import tarball 파일로부터 이미지를 생성한다.
- 관련된 정보를 출력해주는 명령어
- docker history 이미지의 이력 정보를 보여준다.
- docker tag 이미지에 이름으로 태그를 붙여준다(local 혹은 registry).
- 레지스트리(Registry) & 저장소(Repository)
- docker login 레지스트리에 로그인한다.
- docker search 레지스트리에서 이미지를 검색한다.
- docker pull 이미지를 레지스트리에서 로컬 머신으로 가져온다(pull).
- docker push 이미지를 로컬 머신에서 레지스트리에 집어넣는다(push).
- 기타
- docker –version
- docker info 공식 저장소의 주소를 확인할 수 있음.
- docker create
- docker exec
- docker load
- docker stats
docker run <옵션> <이미지 이름, ID> <명령> <매개 변수="">매개>명령>옵션>
- -p 플래그는 공용 포트를 컨테이너 안의 전용 포트로 재 지정
- -d 스위치를 제공하면 분리 모드에서 컨테이너가 실행되므로 컨테이너가 백그라운드에서 실행
- –rm=false: 컨테이너 안의 프로세스가 종료되면 컨테이너를 자동으로 삭제합니다. -d 옵션과 함께 사용할 수 없습니다.
- –name 이름을 지정하는 플래그
- -i, –interactive=false: 표준 입력(stdin)을 활성화하며 컨테이너와 연결(attach)되어 있지 않더라도 표준 입력을 유지합니다. 보통 이 옵션을 사용하여 Bash에 명령을 입력합니다.
- -t, –tty=false: TTY 모드(pseudo-TTY)를 사용합니다. Bash를 사용하려면 이 옵션을 설정해야 합니다. 이 옵션을 설정하지 않으면 명령을 입력할 수는 있지만 셸이 표시되지 않습니다.
- 마지막 registry는 실행하고자하는 이미지의 이름입니다.
- -e, –env=[]: 컨테이너에 환경 변수를 설정합니다. 보통 설정 값이나 비밀번호를 전달할 때 사용합니다. -e MYSQL_ROOT_PASSWORD=examplepassword
- -v, –volume=[]: 데이터 볼륨을 설정입니다. 호스트와 공유할 디렉터리를 설정하여 파일을 컨테이너에 저장하지 않고 호스트에 바로 저장합니다. 호스트 디렉터리 뒤에 :ro, :rw를 붙여서 읽기 쓰기 설정을 할 수 있으며 기본 값은 :rw입니다. 자세한 내용은 ‘6.4 Docker 데이터 볼륨 사용하기’를 참조하기 바랍니다. <컨테이너 디렉터리=""> 예) -v /data <호스트 디렉터리="">:<컨테이너 디렉터리=""> 예) -v /data:/data <호스트 디렉터리="">:<컨테이너 디렉터리="">:<ro, rw> 예) -v /data:/data:ro <호스트 파일="">:<컨테이너 파일=""> 예) -v /var/run/docker.sock:/var/run/docker.sock 컨테이너>호스트>컨테이너>호스트>컨테이너>호스트>컨테이너>
$ docker run -p 49160:8080 -d klnet.owner/klnet.owner.web
$ docker run -p 80:8080 -d klnet.owner/klnet.owner.web
$ docker run -d --name "server" -p 5000:5000 klnet.owner.node
$ docker run -d --name "client" -p 80:80 --link server klnet.owner.web
$ docker run -it --rm -p 8000:8000 django-sample ./manage.py runserver 0:8000
$ docker run -it --rm postgres
$ docker run --rm --name db -e POSTGRES_DB=djangosample -e POSTGRES_USER=sampleuser -e POSTGRES_PASSWORD=samplesecret postgres
$ docker run -it --rm -p 8000:8000 --link db -e DJANGO_DB_HOST=db -e DJANGO_DEBUG=True django-sample ./manage.py runserver 0:8000
$ docker run -it --rm -p 8000:8000 --link db -e DJANGO_DB_HOST=db -e DJANGO_DEBUG=True --volume=$(pwd):/app/ django-sample ./manage.py runserver 0:8000
--volume: 이 옵션을 사용하여 로컬 디렉터리의 특정 경로를 컨테이너 내부로 마운트할 수 있습니다. ($(pwd)는 이 명령을 실행하는 현재 디렉터리의 절대 경로입니다.)
docker ps <옵션>옵션>
- -a, –all=false: 모든 컨테이너를 출력합니다. docker ps 명령은 기본적으로 시작된 컨테이너만 출력합니다.
- –before=””: 특정 컨테이너가 생성되기 전에 생성된 컨테이너를 출력합니다. 정지된 컨테이너도 포함됩니다.
- -f, –filter=[]: 출력 필터를 설정합니다. 예) “exited=0”
- -l, –latest=false: 가장 마지막에 생성된 컨테이너를 출력합니다. 정지된 컨테이너도 포함됩니다.
- -n=-1: 숫자를 지정하여 최근에 생성된 컨테이너를 일정 개수만 출력합니다. 정지된 컨테이너도 포함됩니다.
- –no-trunc=false: 내용이 길어서 생략된 부분을 모두 출력합니다.
- -q, –quiet=false: 컨테이너 ID만 출력합니다.
- -s, –size=false: 컨테이너에서 변경된 데이터의 크기를 출력합니다.
- –since=””: 특정 컨테이너가 생성된 후에 생성된 컨테이너를 출력합니다. 정지된 컨테이너도 포함됩니다.
docker build <옵션> 옵션>
- –force-rm=false: 이미지 생성에 실패했을 때도 임시 컨테이너를 삭제합니다.
- –no-cache=false: 이전 빌드에서 생성된 캐시를 사용하지 않습니다. Docker는 이미지 생성 시간을 줄이기 위해서 Dockerfile의 각 과정을 캐시하는데, 이 캐시를 사용하지 않고 처음부터 다시 이미지를 생성합니다.
- -q, –quiet=false: Dockerfile의 RUN이 실행한 출력 결과를 표시하지 않습니다.
- –rm=true: 이미지 생성에 성공했을 때 임시 컨테이너를 삭제합니다.
- -t, –tag=””: 저장소 이름, 이미지 이름, 태그를 설정합니다. <저장소 이름="">/<이미지 이름="">:<태그> 형식입니다. hello hello:0.1 exampleuser/hello exampleuser/hello:0.1태그>이미지>저장소>
$ docker build -t klnet.owner/klnet.owner.web .
docker start <옵션> <컨테이너 이름, ID>옵션>
- -a, –attach=false: 컨테이너에 표준 입력(stdin), 표준 출력(stdout), 표준 에러(stderr)를 연결하고 모든 시그널을 전달합니다.
- -i, –interactive=false: 표준 입력(stdin)을 활성화 합니다.
docker stop <옵션> <컨테이너 이름, ID>옵션>
- -t, –time=10: 컨테이너를 정지하기 전에 대기하는 시간을 설정합니다. 초 단위입니다.
docker kill <옵션> <컨테이너 이름, ID>옵션>
- -s, –signal=”KILL”: 특정 시그널을 보냅니다.
$ sudo docker run -i -t -d --name hello ubuntu:14.04 /bin/bash
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0660ca3469bf ubuntu:14.04 "/bin/bash" 3 seconds ago Up 2 seconds hello
$ sudo docker kill hello
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
docker restart <옵션> <컨테이너 이름, ID>옵션>
- -t, –time=10: 일정 시간동안 컨테이너가 정지될 때까지 기다렸다가 컨테이너를 재시작합니다. 초 단위로 설정합니다.
$ sudo docker run -i -t -d --name hello ubuntu:14.04 /bin/bash
$ sudo docker restart hello
docker images
- Local 이미지 확인
docker tag
- 같은 이미지에 새로운 이름이 부여된다.
$ docker tag klnet.owner.web mamma1234/klnet.owner.web
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
klnet.owner.web latest 677a7d6fbf49 10 minutes ago 231.1 MB
mamma1234/klnet.owner.web latest 677a7d6fbf49 10 minutes ago 231.1 MB
docker login
- Docker hub 에 로그인한다.
docker pull
- Docker Hub 에 다운로드한다.
mamma1234/klnet.owner.web:latest
docker push
- Docker Hub 에 업로드한다.
$ docker push mamma1234/klnet.owner.web
docker history
- 이미지 히스토리 확인한다.
$ docker history klnet.owner.web
docker commit
docker rm
docker rmi
docker exec
- docker exec -it c456623003b1 /bin/bash
- docker exec -it c456623003b1 /bin/sh
docker logs
- docker logs 명령은 컨테이너의 표준 출력을 표시함으로써 애플리케이션 상태를 알 수 있다.
docker log [container name]
docker logs mariadb
- 마지막 로그의 10줄만 표시한다
docker logs --tail 10 mariadb
- –since 옵션은 입력 받은 유닉스 시간 이후의 로그를 확인할 수 있으며 -t옵션으로 타임 스탬프를 표시할 수도 있다.
docker logs --since 1549150300 -t mariadb
- -f 옵션을 사용하면 실시간으로 생성되는 로그를 스트림으로 확인할 수 있다.
docker logs --tail 10 -f mariadb
- 로깅 드라이버는 기본적으로 json-file로 설정되지만 도커 데몬 시작 옵션에서 –log-driver 옵션을 사용하여 기본적으로 사용할 로깅 드라이버를 변경할 수 있다. 아래 스크립트는 nonoe 로깅드라이버로 alpine 컨테이너를 시작한다.
docker run -it --log-driver none alpine ash
- 실행중인 컨테이너의 로깅 드라이버를 확인하려면 docker inspect 명령을 실행한다.
docker inspect -f '' <CONTAINER>
docker inspect -f '' mariadb
- 현재 로깅 드라이버는 매우 다양하게 지원되고 있으며 아래 링크에서 지원되는 드라이버를 확인할 수 있다.
- Configure logging drivers : https://docs.docker.com/config/containers/logging/configure/
팁
- 마지막에 실행된 컨테이너의 ID
alias dl=’docker ps -l -q’
docker run ubuntu echo hello world
docker commit
dl
helloworld - 명령어와 함께 커밋하기
docker commit -run=’{“Cmd”:[“postgres”, “-too -many -opts”]}’
dl
postgres - IP address 정보
docker run -i -t ubuntu /bin/bash
- 명령어를 사용하거나 아래 명령어를 사용합니다.
wget http://stedolan.github.io/jq/download/source/jq-1.3.tar.gz
tar xzvf jq-1.3.tar.gz
cd jq-1.3
./configure && make && sudo make install
docker inspect
dl
| jq -r ‘.[0].NetworkSettings.IPAddress’
- 명령어를 사용하거나 아래 명령어를 사용합니다.
wget http://stedolan.github.io/jq/download/source/jq-1.3.tar.gz
tar xzvf jq-1.3.tar.gz
cd jq-1.3
./configure && make && sudo make install
docker inspect
- 이미지의 환경 변수 읽어오기 docker run -rm ubuntu env
- 오래된 컨테이너들 삭제하기 docker ps -a | grep ‘weeks ago’ | awk ‘{print $1}’ | xargs docker rm
- 멈춰있는 컨테이너들 삭제하기
docker rm
docker ps -a -q
- 이미지의 의존관계 이미지로 출력하기 docker images -viz | dot -Tpng -o docker.png
- 모든 컨테이너 삭제하기 docker stop $(docker ps -a -q) docker rm $(docker ps -a -q)
- 모든 이미지 삭제하기 docker rmi $(docker images -q)
- Exit 상태의 모든 컨테이너 삭제하기 docker rm $(docker ps –filter ‘status=exited’ -a -q)
docker ubuntu 예시
- docker pull ubuntu:latest
- docker pull <이미지 이름="">:<태그>태그>이미지>
- docker images : 이미지의 목록을 출력
-
docker run -i -t –name hello ubuntu /bin/bash : 이미지를 컨테이너로 생성한 뒤 Bash Shell을 실행
- docker run <옵션> <이미지 이름=""> <실행할 파일=""> 형식입니다. 여기서는 ubunbu 이미지를 컨테이너로 생성한 뒤 ubuntu 이미지 안의 /bin/bash를 실행합니다. 이미지 이름 대신 이미지 ID를 사용해도 됩니다.실행할>이미지>옵션>
- -i(interactive), -t(Pseudo-tty) 옵션을 사용하면 실행된 Bash Shell에 입력 및 출력을 할 수 있습니다. 그리고 –name 옵션으로 컨테이너의 이름을 지정할 수 있습니다. 이름을 지정하지 않으면 Docker가 자동으로 이름을 생성하여 지정합니다.
- 참고 : CentOS에서 아래와 같은 에러가 발생하면
unable to remount sys readonly: unable to mount sys as readonly max retries reached /etc/sysconfig/docker 파일에서 아래와 같이 --exec-driver=lxc를 추가합니다. /etc/sysconfig/docker # /etc/sysconfig/docker # # Other arguments to pass to the docker daemon process # These will be parsed by the sysv initscript and appended # to the arguments list passed to docker -d other_args="--selinux-enabled --exec-driver=lxc" Docker 서비스를 재시작합니다. $ sudo service docker restart
- docker ps -a : 모든 컨테이너 목록을 출력
- docker stop hello
- docker stop <컨테이너 이름="">컨테이너>
- docker start hello
- docker start <컨테이너 이름="">컨테이너>
- docker restart hello
- docker restart <컨테이너 이름="">컨테이너>
- docker attach hello : 컨테이너에 접속
- docker attach <컨테이너 이름="">컨테이너>
- exit, Ctrl+D 를 컨테이너가 정지됨
- Ctrl+P, Ctrl+Q 를 차례로 입력하여 컨테이너 정지없이 빠져나옴
- docker exec hello echo “Hello World” : 외부에서 컨테이너 안의 명령을 실행
- docker exec <컨테이너 이름=""> <명령> <매개 변수="">매개>명령>컨테이너>
docker nginx 예시
- docker search –filter “is-official=true” nginx
- docker pull nginx
- docker run –name ngnix-test -p 8080:80 nginx
- curl http://127.0.0.1:8080
- docker ps
- docker network ls
- docker network inspect bridge
docker 이미지 생성하기
- makir example
- cd example
- example/Dockerfile
FROM ubuntu:14.04
MAINTAINER Foo Bar <foo@bar.com>
RUN apt-get update
RUN apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
RUN chown -R www-data:www-data /var/lib/nginx
VOLUME ["/data", "/etc/nginx/site-enabled", "/var/log/nginx"]
WORKDIR /etc/nginx
CMD ["nginx"]
EXPOSE 80
EXPOSE 443
- docker build –tag hello:0.1 .
- docker build <옵션>
옵션>
- docker build <옵션>
- docker images
- docker run –name hello-nginx -d -p 80:80 -v /root/data:/data hello:0.1
-d 옵션은 컨테이너를 백그라운드로 실행합니다.
-p 80:80 옵션으로 호스트의 80번 포트와 컨테이너의 80번 포트를 연결하고 외부에 노출합니다. 이렇게 설정한 뒤 http://<호스트 IP>:80에 접속하면 컨테이너의 80번 포트로 접속됩니다.
-v /root/data:/data 옵션으로 호스트의 /root/data 디렉터리를 컨테이너의 /data 디렉터리에 연결합니다. /root/data 디렉터리에 파일을 넣으면 컨테이너에서 해당 파일을 읽을 수 있습니다.
- 웹 브라우저를 실행하고, http://<호스트 IP="">:80으로 접속합니다. Welcome to nginx! 페이지가 표시될 것입니다.호스트>
docker 기타 명령
- docker history hello:0.1 : 이미지의 히스토리를 조회
- docker history <이미지 이름="">:<태그>태그>이미지>
- docker cp hello-nginx:/etc/nginx/nginx.conf ./ : hello-nginx 컨테이너에서 파일을 꺼내보겠습니다.
- docker cp <컨테이너 이름="">:<경로> <호스트 경로="">호스트>경로>컨테이너>
- 현재 디렉터리에 nginx.conf 파일이 복사됨
- docker commit -a “Foo Bar foo@bar.com” -m “add hello.txt” hello-nginx hello:0.2 : 컨테이너의 변경 사항을 이미지 파일로 생성합니다.
- docker commit <옵션> <컨테이너 이름=""> <이미지 이름="">:<태그>태그>이미지>컨테이너>옵션>
- docker diff hello-nginx : 컨테이너가 실행되면서 변경된 파일 목록을 출력
- docker inspect hello-nginx : 이미지와 컨테이너의 세부 정보를 출력합니다.
컨테이너 연결하기
- 웹 서버 컨테이너와 DB 컨테이너가 있을 때 웹 서버 컨테이너에서 DB 컨테이너에 접근할 수 있어야 합니다. 이 때에는 docker run 명령에서 –link 옵션을 사용하여 컨테이너를 연결합니다.
- docker run –name db -d mongo
- docker run –name web -d -p 80:80 –link db:db nginx
Docker NetWork
Bridge
- ifconfig
iptables -t nat -L | more
- docker ps
- brctl show
- docker network ls
- docker network inspect bridge
"IPAM": .... "Subnet":"172.17.0.0/16" "Containers": .... "IPV4Address":"172.17.0.2/16"
- ip a
- route -n
- docker network create server
network tool
- docker … /bin/bash
- apt update
- apt install net-tools #ifconfig, netstat
- apt install iputils-ping
-
apt install traceroute
- curl -v https://172.17.0.1:6379
- curl -v http://172.17.0.1:5001/auth/getTestQuerySample
docker 그룹 추가
- ROOT> sudo usermod -a -G docker $USER
- ROOT> sudo service docker restart
Docker 이미지 관리
- docker login
- docker images
- docker tag nginx:latest mamma1234/nginx-test:v0.1
- docker images
- docker push mamma1234/nginx-test:v0.1
- docker pull mamma1234/nginx-test:v0.1
Docker Dockerfile
FROM
- 기본 이미지를 지정한다. 최근에는 경량화된 운영체제인 Alpine Linux를 많이 사용함.
FROM "사용할 이미지 이름"
$ FROM centos:latest'
MAINTAINER/LABEL
- 이미지를 생성한 저자에 대한 정보 및 라벨링을 할 수 있다. 최근에는 LABEL을 많이 사용한다.
MAINTAINER "이미지 생성한 사람 관련 정보"
$ MAINTAINER PARK DAE KYU mamma1234@gmail.com
RUN
- 패키지 인스톨 및 Shell 명령을 기본이미지를 실행 할때, 함께 수행할 수 있다.
RUN "기본 이미지에서 스크립트 또는 명령 실행시키는 명령어"
$ RUN yum -y update
$ RUN yum -y install net-tools
CMD
- 이미지를 통해 컨테이너가 만들어지고 나서 가장 처음 실행될 명령어를 선언한다. 단 한번만 적용되기 때문에, 필요에 따라 지정해서 사용하면 된다.
CMD "컨테이너에서 실행할 명령어를 실행시키는 명령"
$ CMD touch /home/test.txt
EXPOSE
- EXPOSE는 docker run –expose 옵션과 동일하여 호스트와 연결될 포트번호를 설정하는 명령이다.
EXPOSE 호스트와 연결할 포트번호를 설정하는 명령
$ EXPOSE 8888 80
ENV
- 환경변수를 설정할 수 있다. Docker run -e와 유사한 결과를 가질수 있다.
ENV "환경변수"
$ ENV nginx_vhost /etc/nginx/sites-available/default
ADD
- 현재 폴더 내부의 파일을 이미지에 추가할 수 있으며, 반드시 절대경로를 지정한다.
- ADD pinpoint-agent-1.8.4.tar.gz /pinpoint
ADD http://test.com/test.txt /home/test/
# Image 내부 /home/test 폴더에 test.txt를 저장
COPY
- ADD와 유사하지만 URL, tar에 대한 압축을 풀 수는 없다.
- COPY src1 src2 … dest
- COPY [“src1”, “src2”, …, “dest”]
ENTRYPOINT
- 컨테이너가 실행될 때 사용할 명령어를 지정할 수 있다.
- ENTRYPOINT [“실행명령어”, “인자1”, “인자2”, … ]
- ENTRYPOINT echo hello = /bin/sh -c ‘echo hello’
VOLUME
- 지정된 호스트 보륨에 특정 디렉토리를 저장할 수 있도록 마운트 시킬 수 있다.
VOLUME ["호스트 디렉토리", "이미지 내부 디렉토리"]
$ VOLUME ["/home/parkdk", "/home/guest"]
USER
- RUN, CMD, ENTRYPOINT에서 실행될 계정을 선언한다.
USER "User Name"
$ USER admin
ONBUILD
- ONBUILD는 최초 이미지를 생성할 때는 동작하지 않으며, 최초에 생성된 이미지에 바인딩되어 이후 해당 이미지를 부모 이미지로 기반으로 자식 이미지들을 만들 때 자동으로 바인딩 된다.
ONBUILD RUN touch /thisisremade.txt
WORKDIR
- 명령을 실행하게 되는 디렉토리를 설정하는 명령이다. 주로 RUN, CMD, ENTRYPOINT에서 설정한 실행 파일이 실행될 디렉토리가 된다.
WORKDIR "작업 디렉토리"
$ WORKDIR "/home/parkdk"
Dockerfile 예제
# VERSION 1.0
FROM alpine
# alpine linux 이미지를 기본으로 사용
MAINTAINER PARK DAE KYU, mamma1234@gmail.com
# 생성자 표시
# basic package install, pip install
RUN apk update \
&& apk upgrade \
&& apk add vim git python python-dev py-pip gcc g++ make bash \
&& pip install flask flask-admin flask-bootstrap flask-cors flask-httpauth flask-sqlalchemy flask-wtf gitpython \
&& pip install graphviz ipaddress jsonschema py-radix pymysql requests tabulate websocker-client deepdiff
# Apline linux 생성 이후 설치 패키지
# acitoolkit setup
RUN git clone https://github.com/datacenter/acitoolkit.git \
&& cd /acitoolkit \
&& python ./setup.py install \
&& cd /acitoolkit \
&& python ./setup.py develop
# nxtoolkit setup
RUN git clone https://github.com/datacenter/nxtoolkit.git \
&& cd /nxtoolkit \
&& python ./setup.py install \
&& cd /nxtoolkit \
&& python ./setup.py develop
# CiscoUCSM SDK setup
RUN git clone https://github.com/CiscoUcs/ucsmsdk \
&& pip install ucsmsdk \
&& cd /ucsmsdk \
&& make install
# vmware SDK pyvmomi setup
RUN pip install pyvmomi \
&& git clone https://github.com/mamma1234/mamma1234_pyvmomi-community-samples.git
WORKDIR /
# 실행 디렉토리
CMD ["bin/bash"]
# docker run에서 실행될 때 가장 먼저 실행.
docker Node.js 예시
- package.json
{
"name": "docker_web_app",
"version": "1.0.0",
"description": "Node.js on Docker",
"author": "First Last <first.last@example.com>",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.16.1"
}
}
- server.js
'use strict';
const express = require('express');
// 상수
const PORT = 8080;
const HOST = '0.0.0.0';
// 앱
const app = express();
app.get('/', (req, res) => {
res.send('Hello World');
});
app.listen(PORT);
console.log('Running on http://localhost:' + PORT);
- Dockerfile
FROM node:latest
# 앱 디렉터리 생성
WORKDIR /usr/src/app
# 앱 의존성 설치
# 가능한 경우(npm@5+) package.json과 package-lock.json을 모두 복사하기 위해
# 와일드카드를 사용
COPY package*.json ./
RUN npm install
# 프로덕션을 위한 코드를 빌드하는 경우
# RUN npm ci --only=production
# 앱 소스 추가
COPY . .
EXPOSE 8080
CMD [ "node", "server.js" ]
- .dockerignore
node_modules
npm-debug.log
-
이미지 빌드
- docker build -t klnet.owner/klnet.owner.web .
-
이미지 실행
- docker run -p 49160:8080 -d klnet.owner/klnet.owner.web
-
docker run -p 80:8080 -d klnet.owner/klnet.owner.web
- docker run -d –name “server” -p 5000:5000 klnet.owner.node
- docker run -d –name “client” -p 80:80 –link server klnet.owner.web
Proxy error: Could not proxy request
Proxy error: Could not proxy request /api/getScheduleDetailList from 172.19.1.22 to http://172.19.1.22:5000/.
See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (EHOSTUNREACH).
sudo lsof -iTCP -sTCP:LISTEN -n -P
docker run으로 컨테이너를 시작할 때 iptables 오류
iptables error when starting container with docker run
[root@owner ~]# docker run -d -it --rm --name "server" -p 5000:5000 -v /KLNET/OWNER:/OWNER klnet.owner.node
3b5df5ab4859a3da81d55ad933e9d456f1898a47d9e6a0a1f25b65ca6935cd9a
docker: Error response from daemon: driver failed programming external connectivity on endpoint server (855c7a9b6d55525c2088cbda26962388eb1d3692b520823265f2ed04304ca627): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 5000 -j DNAT --to-destination 172.17.0.2:5000 ! -i docker0: iptables: No chain/target/match by that name.
(exit status 1)).
-
Ensure the firewalld service has been started with:
- sudo systemctl start firewalld.service
-
You can verify the service is running with:
- systemctl status firewalld.service
-
service docker restart
-
그래도 안된다면.. 추가
-- iptables에 Docker Chain 추가 *
iptables -t nat -N DOCKER
iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL ! --dst 127.0.0.0/8 -j DOCKER
service iptables save
service iptables restart
iptables -L
service docker restart
- firewalld가 iptables을 건드는 것 막고 싶으면, firewalld 동작을 중지 시키면 된다.
sudo systemctl stop firewalld
sudo systemctl disable firewalld
sudo systemctl mask firewalld <-- 재 부팅 시에도 안 올라오게 하고 싶을 경우.
Docker - No route to host
- docker *11 connect() failed (113: No route to host)
[root@docker-host ~]# iptables -S INPUT
-P INPUT ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -i docker0 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
[https://stackoverflow.com/questions/40214617/docker-no-route-to-host] (https://stackoverflow.com/questions/40214617/docker-no-route-to-host)
iptables -I INPUT 4 -i docker0 -j ACCEPT
centos 7 docker no route to host
[https://ggami.net/648/docker-centos8-fedora%EC%97%90%EC%84%9C-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-host-%EC%82%AC%EC%9A%A9-%EB%B6%88%EA%B0%80%EB%8A%A5%ED%95%9C-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95/] (https://ggami.net/648/docker-centos8-fedora%EC%97%90%EC%84%9C-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-host-%EC%82%AC%EC%9A%A9-%EB%B6%88%EA%B0%80%EB%8A%A5%ED%95%9C-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95/)
[https://forums.centos.org/viewtopic.php?t=72558] (https://forums.centos.org/viewtopic.php?t=72558)
firewall-cmd --list-all
firewall-cmd --list-all-zones
firewall-cmd --zone=trusted --add-interface=docker0
firewall-cmd --zone=public --add-port=80/tcp
firewall-cmd --reload
firewall-cmd --add-service=sip --permanent
firewall-cmd --add-service=http --permanent
firewall-cmd --add-service=https --permanent
firewall-cmd --permanent --zone=trusted --add-interface=docker0
firewall-cmd --permanent --zone=trusted --add-port=4243/tcp
firewall-cmd --reload
systemctl restart docker
open all IPs starts with “172” so that all the containers may communicate each other
sudo firewall-cmd –permanent –zone=public –add-rich-rule=’rule family=ipv4 source address=172.0.0.0/8 accept’
make our container able to visit the network outside
sudo firewall-cmd –permanent –zone=public –add-masquerade
apply the change
sudo firewall-cmd –reload
Masquerading allows for docker ingress and egress (this is the juicy bit)
firewall-cmd –zone=public –add-masquerade –permanent
Specifically allow incoming traffic on port 80/443 (nothing new here)
firewall-cmd –zone=public –add-port=80/tcp firewall-cmd –zone=public –add-port=443/tcp
Reload firewall to apply permanent rules
firewall-cmd –reload
docker-compose.yml
- $ docker-compose up -d : 이미지를 빌드하고 서비스를 실행합니다
- docker-compose up -d [서비스_이름] : 알아서 컨테이너를 재생성하고 서비스를 재시작, 서비스를 멈추고(stop), 서비스를 지우고(rm), 서비스를 시작해야(up)
- docker-compose up -d –build [서비스_이름] : 알아서 이미지를 새로 만들고 서비스를 재시작
- -d: 서비스 실행 후 콘솔로 빠져나옵니다. (docker run에서의 -d와 같습니다.)
- –force-recreate: 컨테이너를 지우고 새로 만듭니다.
- –build: 서비스 시작 전 이미지를 새로 만듭니다. 캐싱된 이미지를 체크하지 않고 무조건 빌드를 하고 시작하라는 의미입니다.
- $ docker-compose ps : 현재 환경에서 실행 중인 각 서비스의 상태를 보여줍니다.
- $ docker-compose stop : 서비스를 멈추거나
- $ docker-compose start : 멈춰 있는 서비스를 시작합니다.
- $ docker-compose down –volume : stop 뿐만 아니라 컨테이너 삭제까지, 서비스를 지웁니다. 컨테이너와 네트워크를 삭제하며, 옵션에 따라 볼륨도 지웁니다 - –volume: 볼륨까지 삭제합니다.
- $ docker-compose exec : 실행 중인 컨테이너에서 명령어를 실행합니다. 자동화된 마이그레이션용 파일 생성이나 유닛 테스트, lint 등을 실행할 때 사용합니다. - docker-compose exec django ./manage.py makemigrations
- $ docker-compose logs : 서비스의 로그를 확인할 수 있습니다. logs 뒤에 서비스 이름을 적지 않으면 도커 컴포즈가 관리하는 모든 서비스의 로그를 함께 보여줍니다. - docker-compose logs django, docker-compose logs -f django,
- $ docker-compose build : build 부분에 정의된 대로 빌드
network_mode
network_mode: host
데이터 볼륨 지정
# 호스트 디렉터리:컨테이터 디렉터리
# 컨테이너 내부에서 해당 경로에 접근하면 지정한 호스트 디렉터리로 접근할 수 있다.
# 데이터베이스의 경우 유지되어야 할 파일의 위치를 볼륨으로 지정해 주면
# 볼륨을 삭제하지 않는 한 컨테이너가 재기동되어도 영속성이 유지된다.
volumes:
- /data/postgres:/var/lib/postgresql/data
version: '3'
services:
db:
image: postgres
volumes:
- ./docker/data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=sampledb
- POSTGRES_USER=sampleuser
- POSTGRES_PASSWORD=samplesecret
- POSTGRES_INITDB_ARGS=--encoding=UTF-8
django:
build:
context: .
dockerfile: ./compose/django/Dockerfile-dev
environment:
- DJANGO_DEBUG=True
- DJANGO_DB_HOST=db
- DJANGO_DB_PORT=5432
- DJANGO_DB_NAME=sampledb
- DJANGO_DB_USERNAME=sampleuser
- DJANGO_DB_PASSWORD=samplesecret
- DJANGO_SECRET_KEY=dev_secret_key
ports:
- "8000:8000"
command:
- python manage.py runserver 0:8000
volumes:
- ./:/app/
- version : 파일의 규격에 따라 지원하는 옵션이 달라지는데, “3”이라만 적으면 3으로 시작하는 최신 버전을 사용한다는 의미
- services : 이 항목 밑에 실행하려는 컨테이너들을 정의합니다. 컴포즈에서는 컨테이너 대신 서비스라는 개념을 사용합니다.
- db : postgres 서비스의 이름을 db로 정하였습니다.
- image : db 서비스에서 사용할 도커 이미지를 적습니다. 여기서는 dockerhub의 공식 postgres 이미지를 사용하였습니다.
- volumes : docker run으로 db 컨테이너를 실행할 때 –volume 옵션을 사용하여 데이터베이스의 데이터를 로컬 컴퓨터에 저장했던 부분과 같습니다. 다만 docker-compose.yml의 volumes에는 상대 경로를 지정할 수 있어서 편리합니다.
- environment : docker run 명령어의 -e 옵션에 적었던 내용들입니다. 마지막의 POSTGRES_INITDB_ARGS 부분이 추가되었는데, 데이터베이스 서버의 인코딩을 UTF-8로 설정하기 위함입니다.
- django : 앱 서비스의 이름은 django로 지정하였습니다.
- build :
- context : context는 docker build 명령을 실행할 디렉터리 경로라고 보시면 됩니다.
- dockerfile : ‘개발용’ 도커 이미지를 빌드하는 데 사용할 Dockerfile을 지정하면 됩니다.
- ports : docker run 명령어의 -p 옵션에 해당하는 부분입니다.
- command : docker run으로 앱 컨테이너를 실행할 때 가장 마지막에 적었던 명령어 부분입니다.
- image : db서비스에서 사용할 이미지 명을 적습니다.
- links :
- external_links :
- ports : docker run -p 옵션에 해당하는 부분입니다.
- expose :
- volumes_from :
- environment : Django 설정파일에서 불러와 사용하게 됩니다. (db관련 정보들은 db서비스에서 설정한 값들과 일치해야 합니다.)
- env_file :
- container_name :
- labels :
Docker Volume (호스트 볼륨 공유)
컨테이너 데이터를 호스트 디스크에 저장하기
Version : Docker
Docker 이미지로 컨테이너를 생성하면 이미지는 읽기 전용이 되며 컨테이너의 변경된 부분만 별도로 저장해서 컨테이너의 정보를 보존한다. 컨테이너에 저장된 데이터는 컨테이너가 삭제되면 데이터가 함께 삭제된다. 이러한 문제를 해결하기 위해서 데이터를 영속적(Persistent)로 저장하는 방법에는 몇 가지가 있으며 이번 포스트에서는 볼륨(Volume)에 대해서 살펴본다.
볼륨은 Docker 컨테이너에 의해 생성되고 Docker컨테이너에 의해 사용되는 데이터를 유지하는 기본 메커니즘이다. 바인드 마운트는 호스트 시스템의 디렉터리 구조에 따라 다르지만 Volume은 Docker에 의해 완벽하게 관리된다. 볼륨에는 바인드 마운트에 비해 몇 가지 장점이 있다.
바인드 마운트보다 볼륨을 백업하거나 마이그레이션 하는 것이 더 쉽다.
Docker CLI 명령 또는 Docker API를 사용하여 볼륨을 관리할 수 있다.
볼륨은 Linux 및 Windows컨테이너에서 작동한다.
볼륨은 여러 컨테이너간에 안전하게 공유할 수 있다.
볼륨 드라이버를 사용하면 원격 호스트 또는 클라우드 공급자에 볼륨을 저장하고 볼륨 내용을 암호화하거나 다른 기능을 추가할 수 있다.
새 볼륨은 컨테이너에 의해 미리 채워진 내용을 가질 수 있다.
호스트 볼륨을 공유하는 방법은 컨테이너를 생성할 때 -v 옵션을 사용하여 호스트의 디렉터리와 컨테이너 디렉터리를 공유한다. 아래 예제는 호스트의 myvol2볼륨을 컨테이너의 /app에 마운트 한다.
docker run -d –name devtest -v myvol2:/app nginx:latest
만약 마운트 하려는 볼륨이 호스트에 존재하지 않으면 호스트에 해당 디렉터리가 생성되면서 컨테이너와 공유 된다(컨테이너의 파일이 호스트로 복사됨). 이렇게 -v 옵션으로 공유된 디렉터리는 컨테이너가 삭제되더라도 호스트의 디렉터리는 삭제되지 않기 때문에 데이터를 보전할 수 있다. 볼륨 공유는 디렉터리 단위 뿐만 아니라 파일 단위의 공유도 가능하며 여러 개의 -v 옵션을 사용하여 동시에 여러 볼륨 공유도 가능하다.
만약 호스트에 이미 디렉터리가 존재하고 컨테이너에도 존재할 때 두 디렉터리를 공유하면 어떻게 될까? 결과적으로는 컨테이너의 파일이 삭제되고 호스트의 파일이 공유된다. 즉, 컨테이너의 디렉터리 자체가 덮어 써지는 것이다. (호스트의 디렉터리가 컨테이너의 디렉터리에 마운트 되는 방식이다.)
아래 실습은 MAC에 설치된 Docker 환경에서 Volume을 공유하는 예시이다. 우선 볼륨을 공유하기 전에 Docker 속성에서 호스트(MAC)의 디렉터리가 공유되어 있는지 확인한다. 호스트의 디렉터리가 아래 Docker 환경에 공유되어 있지 않으면 사용할 수 없다.
필자의 경우 이미 다운로드 받은 이미지를 컨테이너로 실행하면서 볼륨을 공유하였다.
docker run –name friendlyhello -v /tmp/sharetest:/var/sharetest sqlmvp/get-started:part2
docker volume 의 사용방법과 차이점 [출처] docker volume 의 사용방법과 차이점|작성자 이안아범
호스트(MAC)의 /tmp 하위에는 sharetest라는 디렉토리 존재하지 않았지만 컨테이너가 실행되면서 해당 디렉터리가 생성되었다.
컨테이너의 디렉터리를 조회하면 호스트의 sharetest 디렉터리가 공유된 것을 확인할 수 있으며 호스트의 파일이 조회되는 것을 확인할 수 있다.
호스트에서 볼륨을 확인하려면 아래 명령을 실행한다. 볼륨 이름을 지정하지 않으면 무작위의 16진수 형태로 생성된다.
docker volume ls
위에서도 언급하였지만 컨테이너를 삭제한다고 해서 호스트의 볼륨이 삭제되지는 않는다. 따라서 불필요한 볼룸은 호스트에서 수동으로 삭제해주어야 한다. 아래 스크립트는 특정 볼룸을 삭제 한다.
docker volume rm myvol2
아래 스크립트는 모든 볼륨을 삭제 한다.
docker volume prune
docker volume 의 사용방법과 차이점
ocker를 계속 사용하다 보면 container의 데이터 휘발성 때문에 volume을 사용하게 됩니다. volume 사용할 수 있는 방법은 대표적으론 4가지 정도가 있습니다 이번에는 이 방법들 소개와 그 차이에 대해 다룹니다.
그전에 volume 정보를 보는 방법에 대해 하나 알려드리겠습니다.
docker volume ls
위의 명령어를 통해 현재 생성되어 있는 일부 volume들의 정보가 노출됩니다. 왜 일부 volume이냐면 안나오는 놈들도 있습니다. 자세한 내용은 아래에서 확인하세요. 해쉬 id나 이름을 이용해 좀 더 세부정보를 확인할 수도 있습니다.
docker volume inspect {volume_id or volume_name}
- docker run할 때 -v 옵션 host에 바로 맵핑
docker run -itd -v /host/some/where:/container/some/where ubuntu
아주 직관적으로 host의 file system과 container의 파일 시스템이 연결됩니다. 혹시 Dockerfile에 정의된 volume과 같은 경로를 잡는다면 run할 당시의 -v옵션이 image level의 volume을 오버라이드 합니다. Dockerfile에 뭐라 정의되어 있든 사용할 수 있다는 거죠.
좋은 점은 어디서 volume을 잡을지 아주 직관적으로 알 수 있고 volume mapping이 많아질 경우 폴더 구조를 예쁘게 가져가기 쉽습니다. 안 좋은 점은 docker volume ls 같은 명령어로 추적이 안됩니다. container를 run 시킨 사람이 알아서 잘 관리해줘야 한다는 것이죠.
- docker run할 때 -v 옵션 volume create 이용
docker create volume volume_name docker run -itd -v volume_name:/container/some/where ubuntu
/var/lib/docker/volumes에 생성이 되긴 하나 volume_name으로 생성되기 때문에 hash 값으로 생성되는 1번 방법보다는 훨씬 관리하기 편하고 이름이 정해져 있기 때문에 짧은 container 라이프 사이클에서도 계속 사용하기 편합니다. 동시에 폴더가 이름으로 생성되어 훨씬 예쁘게 관리하기 쉽죠. 예를 들면 some-application-db-volume, some-application-app-volume 등의 이름으로 이게 무슨 볼륨인지 바로 알 수 있게 관리하기 쉽습니다. 그러면서 volume ls에서 확인도 가능하죠.
개인적으로 안 좋다고 생각하는건 /var/lib/docker에 계속 종속적이 되기 때문에 용량 관리에 신경을 써야합니다. 모든 container에서 생성되는 데이터가 거기 몰리니까요. disk full나면 난리 나죠. 또한 폴더 이름은 좋게 가져갈 수 있으나 관련 데이터 폴더를 구조적으로 가져갈 수는 없습니다. 하지만 마지막 단점은 3rd party의 driver를 사용하면 데이터 구조 문제는 해결할 수 있긴합니다.
- volume container 마지막으로 volume container를 통해 volume을 연결할 수 있습니다. 1,2,3번 방법 중 하나로 이미 run 되어 있는 상태의 container를 바로 volume으로 잡는 방법인데 volume이 여러개일 때 관리가 쉽죠 예를 들면
docker run –name volume_container -itd -v $HOME/host-volume1:/container-volume1 -v $HOME/host-volume2:/container-volume2: -v $HOME/host-volume3:/container-volume3 ubuntu # 이런식으로 volume이 잡힌 container를 하나 run하고 docker run –name=target_container –volumes-from=volume_container -itd ubuntu
이렇게 container 째로 volume을 붙이는 방법입니다. 같은 볼륨을 여러개의 컨테이너가 참조해야할 때 쓰면 좋죠. target_container에는 volume_container에 선언된 3개의 volume이 모두 마운트됩니다. 그리고 volume_container는 stop되어 있는 상태여도 괜찮습니다.
- docker run할 때 -v 옵션 host에 바로 맵핑 VS docker run할 때 -v 옵션 volume create 이용 차이 volume 자체 선언에 관한 내용은 아니고 2번 방법과 3번 방법의 동작 차이에 대해 설명하려 합니다. 물론 명확한 동작차이는 위에 설명해드렸죠. 여기서 다룰 것은 아주 사소한 동작차이 입니다.
2번 3번 모두 -v option을 통해 쓸 수 있다는 공통점을 가지지만 동작되는 방식에 아주 약간의 차이가 있는데요.
첫번째 -v 옵션으로 host를 바로 마운트시키는 방법입니다. host volume이 비어있고 container volume에 container.txt가 있다고 생각해봅시다. 이걸 마운트하면? 해당 volume은 빈 상태로 container가 런됩니다. 즉 host우선으로 맞추는거죠. 다시 예를 들어 host에 host.txt가 있고 container에 container.txt가 있다면? run 하고나면 host.txt만 남게됩니다. 주의해야겠죠.
반면에 3번 방법은 조금 다릅니다. 우선 두번째 케이스(host에 host.txt가 있고 container에 container.txt가 있는 상황)는 똑같습니다. host 우선으로 맞춰지죠. 근데 첫번째 케이스 host가 비워져있었다면? container의 내용이 그대로 남습니다. 즉, host볼륨에 아무것도 없고. container volume위치에 container.txt 파일이 존재했다면 3번 방법으로 volume 마운트시 run 한 후 확인해보면 container.txt 파일이 그대로 있습니다.
사실 큰 차이는 아닙니다. 왜냐면 mapping 할 volume 위치에 runtime 외의 시간에 데이터를 핸들링 하는 것은 절대 권장되지 않는 것이기 때문이죠. 그러니 그냥 이런 차이가 있다 정도로만 알면 될 것 같습니다.
Centos 7 Docker 삭제
- 설치된 docker 관련 패키지 확인
[root@dpleevbox ~]# yum list installed | grep docker
containerd.io.x86_64 1.2.6-3.3.el7 @docker-ce-stable
docker-ce.x86_64 3:19.03.1-3.el7 @docker-ce-stable
docker-ce-cli.x86_64 1:19.03.1-3.el7 @docker-ce-stable
- containerd, docker-ce, docker-ce-cli 패키지 모두 삭제
[root@dpleevbox bin]# yum erase containerd.io.x86_64
[root@dpleevbox bin]# yum erase docker-ce.x86_64
[root@dpleevbox bin]# yum erase docker-ce-cli.x86_64
-
yum -y remove [설치된 도커 패키지명]
-
/var/lib/docker 아래의 모든 파일, 디렉토리를 삭제한다.
[root@dpleevbox run]# cd /var/lib/docker
[root@dpleevbox docker]# rm -rf *
- /var/run 아래에서 docker.sock, docker.pid 파일과 docker 디렉토리를 삭제한다.
[root@dpleevbox bin]# cd /var/run
[root@dpleevbox run]# rm docker.sock docker.pid
rm: remove 소켓 `docker.sock'? y
[root@dpleevbox run]# rm -rf docker
- 서비스 정리
- systemctl list-unit-files docker
[root@dpleevbox bin]# systemctl stop docker.service
[root@dpleevbox bin]# systemctl stop containerd.service
systemctl unmask containerd.service
systemctl unmask docker.service