도커 - docker command!
docker 개요
가상화 컨테이너 기능은 기존에 있던 리눅스의 lxc(Linux Container)를 사용해 제공되어 왔다.lxc의 핵심인 namespaces, cgroup 을 통해 독립적인 공간 제공과 자원을 공급 역할을 담당한다.
리눅스에서 lxc 사용을 위해 이미지부터 직접만들고 힘들고 번거러움 설정 작업을 해야하는데 2013년 Docker 출시 후 간단한 docker 명령어 몇개로 컨테이너 기능 조작이 가능해졌다.
{: .shadow}
더이상 무거운 virtualbox 혹은 vmware같은 가상화 도구 필요 없이 다양한 서비스 배포가 가능하다.
docker의 경우 hostOS의 자원과 커널을 공유하기에 별도의 guest OS를 설치할 필요가 없다. centOS 컨테이너의 경우 200MB정도밖에 안된다.
{: .shadow}
docker command
설치시 sudo 권한 없이 docker 명령어 실행 필요시 아래 명령어 수행
1 | sudo usermod -aG docker $USER |
docker 컨테이너의 life cycle은 아래와 같다.

docker 명령어를 통해 life cycle 대로 동작시킨다.
docker image 관련 명령어
pull, image, image rm, image inspect, image tag
docker pull image_name:{version}
pull명령은 다운받을 이미지의 이름과 버전을 한 쌍으로 사용한다. 버전 생략시 latest 사용시 최종버전을 설치.
docker pull centos:7: centOS 버전7 이미지 다운
항상 버전을 명시해서 사용하기를 권장
docker image ls: 다운받은 docker 이미목록 조회(docker images 명령도 같은 기능을 수행)
1 | REPOSITORY TAG IMAGE ID CREATED SIZE |
IMAGE ID는 이미지의 고유 코드로 매우 긴 값을 앞의 몇글자만 출력해준다.
이미지 삭제, 컨테이너 생성 등의 명령에서IMAGE ID를 사용하는데 중복되지 않는다면 앞의 3~4글자만 사용해도 상관없다.
(name대신 id를 넣어도 상관 없다 docker rmi imagename으로 사용 가능)
만약 아래와 같은 명령이 출력된다면 해당 이미지로 컨테이너가 생성되 있어 삭제 할 수 없다는 뜻이다.
1 | Error response from daemon: conflict: unable to remove repository reference "mywebserver" (must force) - container 1d37ed64b2c9 is using its referenced image fc4c50b45ccd |
docker image rm -a : 사용하지 않는 이미지 모두 삭제docker image rm imagename: 이미지 삭제docker image rm -f imagename : 이미지 강제로 삭제
docker rmi $(docker images -q) : 이미지 모두 삭제(컨테이너 생성되지 않는 것)
docker image inspect imagename: 이미지의 각종 정보를 확인
이미지의 각종 정보를 --format 속성을 사용해 일부만 출력할 수 있다.
설치된 os, os bit, imageID를 확인해보자
1 | $ docker inspect --format="{{.Os}}" centos:7 |
docker image tag 현재이미지명 변경이미지명: 이미 생성된 이미지에 별칭을 부여, 기존의 이미지를 그대로 사용한다.(이미지는 불변, 링크를 만드는 개념)
권장되는 이미지 명칭 부여 규칙:
username/repositoryname:tag
1 | $ docker image tag nginx kouzie/webserver:1.0 |
아래의 docker hub repository에 만든 내가 만든 이미지를 업로드할 때 위의 이미지 명칭 규칙을 따라야 올릴 수 있다.
docker login, docker image push
도커 허브 public repository에 만든 이미지를 올릴 수 있다. 당연히 로그인 과정을 먼저 거쳐야 한다.
1 | $ docker login |
nginx를 다운받고 해당 이미지를 내 public repository에 올려보자.
1 | $ docker pull nginx |
image tag명령을 통해user_name/repositort_name:tag_name형식으로 이름을 설정필수.
명령이 끝나면 docker hub 페이지에 아래와 같이 repository가 생성되었는지 확인
{: .shadow}
새로 생성한 이미지 리파지토리에 올리기
$ docker container commit -a "kouzie" webserver webserver:nginx
-a : 저자 설정 옵션
$ docker tag webserver:kouzie kouzie/webserver:nginx
1 | $ docker images |
docker image save / load
이미지를 tar파일로 추출 삽입 가능하다.
주로 인터넷 연결이 되지 않는 내부 환경에서 사용하는 명령어
1 | $ docker save mongo > mongo.tar |
docker container - create, start, stop, run, ps, inspect
docker container create imagename
create속성으로 컨테이너 생성가능하다.
(대부분 run 명령을 통해 create와 start를 생략한다.)
docker container start containername
이미 생성한 컨테이너는 start속성으로 시작가능하다.
멈출때에는 docker container stop containername을 사용한다. (container 키워드는 생략 가능하다.)
docker run imagename 의 경우 [image pull], create, start 명령이 합쳐진 명령어이다.
docker run centos:7 echo "hello world": centOS 이미지를 컨테이너로 생성하고 echo명령을 수행
docker run -it --name "ctin_test1" centos /bin/cal: centos:latest버전을 다운받고 /bin/cal 프로그램 실행
1 | $ docker run -it --name "ctin_test1" centos /bin/cal |
docker run -d centos /bin/ping localhost : centos:latest버전을 다운받고 백그라운드로 /bin/ping localhost 프로그램 실행
docker logs -t -f 컨테이너ID, -f는 실시간으로 확인
출력된 컨테이너 id를 가져와
logs명령어로 현재 터미널에 출력된 값을 확인 가능하다.
위에서ping명령을 날리고 있는centos에logs명령으로 접근해서 결과를 확인해보자.
1 | $ docker run -it --hostname=www.test.com --add-host=node1.test.com:192.168.1.1 ubuntu:16.04 |
컨테이너 일시정지, 정지해제는 pause와 unpause 명령을 사용한다.(잘 쓰이진 않음)
1 | $ docker pause container_name |
도커 컨테이너를 생성했다면 hostOS에서 docker0 브릿지와 연결되는 터널링 가상 렌카드가 생성되었는지 확인
1 | veth8d1fe0e Link encap:Ethernet HWaddr 1a:99:df:2d:99:52 |
생성된 컨테이너 만큼의 렌카드가 생성된다.
docker 컨테이너 os 확인
grep . /etc/*-release
docker 컨테이너 실행 속성
-it : interactive tty mode(표준 입출력 터미널)의 약자이다.--name : 컨테이너명 이름 지정-p port1:port2 : port1은 hostOS의 port1, port2은 컨데이너의 port로 매핑한다.-d : --detach=true를 줄임으로 컨테이너를 백그라운드로 실행한다. 명령이 실행되면 컨테이너 고유 id를 반환한다.-P: 포트매핑시 host의 랜덤포트를 부여, 32768 부터 시작한다.
-p (publish)와 Dockerfile의 expose의 차이점
publish의 경우 host와 container같의 포트매핑, expose의 경우 내부적인 포트노출, 같은 대역의 컨테이너들은 접근 가능
docker 컨테이너 확인
docker ps: 현재 실행중인 컨테이너 목록 확인docker ps -a: 생성된 컨테이너 목록 확인docker ps -a -f name=cadviser: 컨테이너의 이름을 지정해 확인docker ps -a -f exited=0: 생성된 컨테이너중 종료된 컨테이너 확인
docker container 제거
docker stop $(docker ps -q) : 실행중인 컨테이너 모두 전체 정지docker rm $(docker ps -a -q) : 컨테이너 모두 삭제(exit 된 것)docker prune : 정지중인 컨테이너 모두 삭제
docker 컨테이너 파일 전송 -cp
hostOS에서 컨테이너로의 파일 전송시에는 파일명을 먼저 작성하고docker cp file_name container_name:/file_name
역으로 컨테이너에서 hostOS로의 파일 전송시에는 컨테이너명을 먼저 작성한다.docker cp container_name:/file_name file_name
docker 컨테이너 export / import
컨테이너를 tar파일로 추출 삽입 가능하다.
$ docker export webserver > webserver.tar$ docker import .webserver.tar
docker 컨테이너 commit
생성한 컨테이너를 다시 이미지화 하고 싶다면 docker container commit명령 을 수행하면 된다.
unbuntu 이미지를 다운받고 apache 서버를 설치한뒤 이를 다시 image로 저장
1 | docker run -it --name ubuntu_webserver -P -p 80 ubuntu:16.04 |
docker 컨테이너 정보조회
docker attach
실행중인 컨테이너의 표준 입출력을 연결해주는 명령어
1 | $ docker ps |
docker exec -it name /bin/bash과 같은 명령으로 컨테이너를 실행시키고 입력이 가능한 쉘을 띄어놔야 입출력이 모두 가능하고
단순 백그라운드로 실행시킬 경우 출력되는 로그만 확인 가능하다.
docker diff contain_name
컨테이너 생성후 달라진 파일시스템을 출력하는 명령어useradd testuser 를 컨테이너에서 실행후 아래 명령을 실행
1 | $ docker diff cent-server |
docker inspect
이미지의 정보도 docker image inspect로 확인가능했는데 컨테이너 들도 inspect 명령이 있다.
docker inspect container_name명령을 통해 생성된 컨테이너의 정보를 json형태로 확인 가능
컨테이너를 설치하고 ip를 확인하려면 ifconfig 명령 사용을 위해 net-tools 설치를 해야 확인 가능한데 그런거 필요 없이 아래 명령처럼 inspect로 확인 가능하다.
docker inspect confident_shirley | grep "IPAddress"
1 | "SecondaryIPAddresses": null, |
빠져나가는건
ctrl + p + q(exit을 사용하면docker컨테이너가 stop되어버린다)
만약 컨테이너 안에서exit명령으로도 계속 컨테이너 실행상태를 유지하고 싶다면--restart=”always”속성을 사용해 컨테이너를 실행한다.
다시 들어가려면 docker exec 으로 bash을 실행하면 된다.docker exec -it confident_shirley /bin/bash
hello world 찍을때 생성되었던 centos 컨테이너로 접속
ifconfig명령 수행을 위해yum install net-tools를 설치
docker container stats: 컨테이너 실행 상태 확인 (메모리, cpu, disk I/O 등이 출력된다)
1 | CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS |
google cadviser - docker 모니터링
구글에서 제공하는 docker 모니터링 도구이다. 다른 컨테이너를 감시하는 또 하나의 도커 컨테이너이다.
docker run명령과 함께 볼륨을 일치시켜주는 속성을 적용
1 | docker run \ |
볼륨은 후에 살펴보겠지만 hostOS와 컨테이너간 파일 시스템을 일부 공유할 수 있게 해주는 속성이다.
다른 도커 컨테이너들을 모니터링 하려면 hostOS의 협력이 필요하기에 hostOS의 저장소를 google cadviser컨테이너와 일치시켜주어야 한다.
8080포트로 접속해 구동중인지 확인.
모니터링할 docker 컨테이너를 nginx로 만들어보자.docker run --name webserver -d -p 80:80 nginx
아래와 같은 실시간 모니터링 화면이 출력된다.
{: .shadow}
80포트로 계속 새로고침을 누르며 webserver컨테이너가 사용하는 cpu, memory, network 사용량 변화를 확인
docker network
docker engine을 설치하면 가상 브릿지 네트워크가 생긴다(docker0).virtual ethernet bridge라 칭한다.
{: .shadow}
컨테이너를 가동하면 vethxxxxxxx형태의 컨테이너 내부의 인터페이스(eth0)와 통신하는 가상의 peer가 생성되고 게이트웨이와 통신하는 접점역할을 수행한다
(direct 케이블 연결 형식의 격리된 네트워크 공간을 제공).
최종적으론 docker0로 사용해 host네트워크를 통해 외부네트워크와 통신한다.
docker network command
docker에서 사용하는 브릿지 목록을 확인하기 위해 brctl 설치
1 | $ sudo apt-get install bridge-utils |
현재 docker0 브릿지에 접근하는 2개의 peer를 확인할 수 있다.(컨테이너 2개 동작중)
docker container 생성시 네트워크 설정을 진행해보자.
1 | $ docker run -d -P -p 80 nginx |
이런식으로 포트번호를 외부로 노출시키는 옵션을 부여해 컨테이너를 생성하면 포트 by 포트로 패킷을 넘기는 docker-proxy 프로세스가 생성된다.
kernel이 아닌 user단에서 수행되기 때문에 host가 받은 패킷을 그대로 container의 port로 전송한다.
1 | $ docker netowrk ls |
docker0와 같은 기본 브릿지네트워크 말고도 다른 네트워크 옵션을 사용할 수 있다.hostOS와 같은 네트워크 대역을 사용할건지 네트워크를 아예 사용하지 않을것이지 선택 가능하다.
docker network inspect bridge
현재 bridge 에 붙어있는 컨테이너들의 네트워크 정보를 간략히 조회 가능
1 | "Containers": { |
docker network create
docker0는 일종의 소프트웨어적인 스위치 개념으로 아래와 같은 대역을 갖는다.
1 | docker0 Link encap:Ethernet HWaddr 02:42:92:bd:f8:8f |
또한 컨테이너 생성시 기본적으로 할당되는 브릿지이다.
별도의 분리된 브릿지 네트워크를 생성하고 컨테이너를 생성해 해당 브릿지에 붙여보자.
1 | $ docker network create -d bridge webap-net |
-d, --driver : 네트워크를 bridge, host, none 등으로 설정할 때 사용
br-a9d59233db3b라는 이름의 인터페이스가 생성되었다. 18의 B class의 ip대역을 갖는다.
물론 속성을 통해 ip 대역을 직접 설정 가능하다.
1 | $ docker network create --driver bridge --subnet 172.100.1.0/24 --ip-range 172.100.1.0/24 --gateway=172.100.1.1 vswitch01 |
docker network ls 명령으로 네트워크 검색을 해보면
1 | $ docker network ls |
기존에 만들었던 webap-net과 vswitch01가 추가됨을 확인 가능하다.
docker 컨테이너 ip 확인
컨테이너 생성시 --net 속성으로 사용할 네트워크 인터페이스를 지정 가능하다.
apt-get install net-tools로 ifconfig를 설치해 ip확인도 가능하지만 ip a나 inspect 속성으로 간단히 확인도 가능하다.
1 | $ docker container run --net=webap-net -it --name mycent centos:7 |
기존 docker0의 대역172.17.0.0/24에서 1 더한 172.18.0.0/24 대역의 bridge가 생성되었다.
그리고 현재 해당 브릿지 네트워크에 붙어있는 컨테이너 정보도 출력되는데--net=webap-net 속성으로 실행시킨 modest_matsumoto 컨테이너의 ip 는 자동으로 172.18.0.2 설정되었다.
docker 컨테이너 - 가상네트워크 - 브릿지 연결 확인
1 | $ brctl show |
brctl show명령으로 확인해보면 브릿지 2개가 동작중이다.
각 컨테이너가 어떤 가상 네트워크 인터페이스를 통해 브릿지에 연결되어 있는지 확인해보자.
단순
컨테이너 - 브릿지연결 정보는docker network inspect혹은 ifconfig 명령으로 대조해서 확인 가능하다.
먼저 아래의 명령으로 modest_matsumoto이름의 컨테이너의 네트워크 정보 확인
1 | $ docker exec modest_matsumoto ip addr show eth0 |
36을 잘 기억해두자.
브릿지만 네트워크 아이디확인
/sys/class/net/ 디렉토리에 접근하면 브릿지를 포함한 각종 네트워크 인터페이스 파일이 존재한다.ifindex 파일을 출력하면 36에서 +1 된 정수가 나올 것인데 해당 인터페이스가 브릿지와 컨테이너를 이어주느 가상 인터페이스이다!
1 | $ cat /sys/class/net/vetha6f982e/ifindex |
modest_matsumoto는 veth220fd5a와 peer를 이루고 있었다.
이제 veth220fd5a 가상 인터페이스가 어떤 브릿지 네트워크와 연결되어있는지 확인하면 된다.
1 | $ brctl show |
brctl show명령으로 어떤 브릿지와 가상 인터페이스간 연결 정보를 확인 가능하다.
즉 modest_matsumoto컨테이너는 veth220fd5a peer와 연결되어 있고
해당 peer는 docker0 브릿지와 연결되어 있다.
docker container 네트워크 붙이기
기존에 생성해둔 webap-net 브릿지 네트워크를 컨테이너에 붙여보자.
1 | $ docker run -it centos:7 bash |
컨테이너 안에서 ifconfig 명령으로 네트워크 인터페이스 확인
1 | [root@ce1f8e20e4db /]# ifconfig |
docker network 삭제
1 | $ docker network rm webap-net |
당연히 기존에 사용중인 네트워크는 삭제가 불가능해서 연결을 끊고 삭제해야한다.
docker network disconnect webap-net dreamy_wilbur 혹은 컨테이너를 stop하고 삭제해도 상관없다.
127.0.0.11
docker 내부의 dns서버 IP는 127.0.0.11
호스트의 이름을 유동적인 컨테이너를 찾을 때 주로 사용
아래와 같이 docker 내부 nginx 에서 서버를 동작중이라면 docker dns 로부터 refresh 수행이 가능하다.
1 | http { |
doker 컨테이너간 통신 - ssh
1 | $ docker run -it --name c7_ssh centos:7 |
설정이 끝났으면 해당 컨테이너를 이미지화 해서 2개의 컨테이너 실행
1 | $ docker commit c7_ssh ssh-test-image:0.0 |
ip확인후 각 컨테이너에 접속해 서로 ssh로 접근시도시 비밀번호 체크를 하는지 확인
1 | $ docker inspect c7_ssh_test1 | grep 172 |
docker 컨테이너 resource limit, 모니터링
3대 리소스 cpu, memory, network를 모니터링
network 모니터링
iptraf-ng라는 툴을 설치해 확인
1 | $ sudo apt-get install iptraf-ng |
실행시키면 다음과 같은 화면이 출력
container -> 실제OS(mac혹은 윈도우)로 ping 요청시 어떻게 출력되는지 확인
memory, cpu 모니터링, 제한
메모리 제한을 하면 아래처럼 실패 메세지가 출력된다.
1 | $ docker run -d --memory=1g --name=nginx_mem_1g nginx |
hostOS의 별도의 커널 설정이 필요
1 | $ sudo vi /etc/default/grub |
메모리 공간 뿐 아니라 스왑 공간까지 제한해보자
1 | $ docker run -m=200m --memory-swap=300m -it ubuntu:16.04 /bin/bash |
cpu모니터링을 htop을 통해 진행하자.
htop 설치sudo apt-get install htop
아무것도 실행하고 있지 않을때 cpu코어 2개와 4g만큼의 메모리를 할당한 우분투의 상태
alicek106/stress라는 테스트용 컨테이너를 설치해 다시한번 모니터링 해보자.
1 | $ docker run -d --name cpu_1024 --cpu-shares 1024 alicek106/stress stress --cpu 1 |
--cpu-shares: cpu할당율을 제한, 1024가 기본값으로 뒤에 값을 줄이거나 늘려 cpu할당률을 늘릴 수 있다.--cpu 1: 사용 코어 개수를 1개로 지정
1 | $ ps -auxf | grep stress |
확실히 cpu점유 시간이 11초 차이가 나긴 하지만 31초의 절반인 15초만큼은 아니다
환경에 따라 cpu 스케줄링 시간을 반절을줘도 거의 비슷한 실행시간을 갖는 경우도 있다. (코어수가 많은경우)
이번엔 두개의 cpu 모두 사용하도록 설정하고 htop으로 사용량 체크docker run -d --name cpuset_2 --cpuset-cpus=0,1 alicek106/stress stress --cpu 2
htop화면
google cadviser 화면
--cpuset-cpus=0,3: 0번째, 3번째 코어만 사용--cpuset-cpus=0-2: 0번째, 1번째, 2번째 코어사용
docker 컨테이너 update
실행중인 컨테이너에 cpu 사용량을 줄이고 싶다면docker update --cpus 0.2 cpuset_1
--cpus: cpu코어 개수를 0.2개로 설정
docker 컨테이너 volume
hostOS와 컨테이너의 파일 공유
먼저 hostOS에 공유할 디렉토리 2개 생성
$ mkdir hello1 hello2
컨테이너 생성시 -v 속성으로 공유 디렉토리 설정
각 폴더에 test라는 파일을 만들고 문자열을 입력한다.
1 | $ cat > hello1/test |
위에서 만든 2개 디렉토리를 ubuntu 컨테이너의 볼륨으로 설정
1 | $ docker run -it --name ubuntu_volume \ |
mount는 2개 모두 출력되지만df는 하나만 확인 가능하다
docker inspect명령으로도 컨테이너에 어떤 디렉토리가 매핑되었는지 확인 가능하다.
1 | $ docker inspect --format="{{ .HostConfig.Binds }}" ubuntu_volume |
참고:
hostOS에 볼륨용 디렉토리를 만들지 않아도 docker 컨테이너 생성시 자동으로 만들어진다.
컨테이너 volume 용량 제한
mkdir 명령으로 myvolume 디렉토리를 만들고 아래 명령을 실행
docker run -v /home/kouzie/myvolume:/webapp -it ubuntu:16.04
docker안에서 df -h명령으로 용량을 확힌해보면 hostOS에서 사용할 수 있는 용량과 같다
/dev/sda1 50G 7.3G 40G 16% /hello1
hostOS의 전체용량인 50G가 출력된다.
이를 hostOS에서 용량제한을 설정할 수 있다. 아래명령을 root 권한에서 실행
/home/kouzie/myvolume 디렉토리를 만들고 용량 제한을 설정한뒤 docker컨테이너에 볼륨설정해보자.
1 | # dd if=/dev/zero of=harddrive.img count=512 bs=1M |
docker run -v /home/kouzie/myvolume:/webapp -it ubuntu:16.04
{: .shadow}
설정댈로 512MB 크기의 용량을 갖는다.
docker 컨테이너 환경설정
환경변수
오라클이나 자바를 사용하려면 환경변수 설정이 필수인데 환경변수를 설정한 파일을 사용해 docker 컨테이너에 적용할 수 있다.
설정할 환경변수가 몇개 안될 경우 -e옵션으로 입력가능하다.docker run -it -e foo=bar centos:7 /bin/bash
컨테이너 안에서 set명령으로 환경변수를 확인.
여러개의 환경변수를 설정할때에는 --evn-file=evn_list
docker run -it --env-file=env_list.txt centos:7 /bin/bash
evn_list.txt파일은 아래처럼 설정
1 | hoge=fuga |
워킹디렉토리
docker의 기본 워킹 디렉토리는 root디렉토리인데 -w 옵션으로 처음 들어갈 때 워킹디렉토리를 지정할 수 있다.
간단한 환경변수설정이나 워킹디렉토리 설정은 옵션으로 지정 가능하지만 여러 설정이 필요한 경우 Dokcerfile이나 docker-compose로 처리하는 경우가 대부분.
docker 컨테이너 연결 - 링크, 네트워크
도커의 철학은 한 컨테이너 안에 DB + WEB + WAS 등 모든 서비스를 묶는 게 아닌 하나의 서비스만을 가볍게 지원하도록 만들어진 개념이다.
각 서비스를 만들고 링크를 걸어보자.
https://hub.docker.com/_/mysql
사이트의 Environment Variables 항목에 필요한 환경변수들이 모두 있다.
1 | $ docker run -d --name wordpressdb -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=wordpress mysql:5.7 |
32768포트에 접속해서 확인해 db에 데이터가 입력되는지 확인해보자.
이번엔 링크가 아닌 네트워크로 연결해 운영해보자.
1 | -- wordpress 전용 network 생성 |
참고: 데이터베이스 데이터가 wp_db와 볼륨을 이루고 있어 공유되고 있는데 해당 컨테이너를 삭제해도 공유된 데이터는 삭제되지 않는다.
docker 볼륨
-v 옵션으로 hostOS와 컨테이너간의 파일 시스템 공유를 했다면
docker volume 명령으로 도커파일에 볼륨을 생성하고 컨테이너간 해당 볼륨을 공유할 수 있다.
1 | $ docker volume create wp-db-volume |