“Docker Practice”讀書筆記

onephone發表於2017-06-18

一本很不錯的Docker入門書籍,github地址, 自己仔細看完了前14章, 提了一個pull request, 修改了3個issue!
關鍵字:docker, Union FS(AUFS), cgroups, namespace

使用映象

  • brew cast install docker
  • docker --version, docker-compose --version, docker-machine --version, docker version, docker info
  • docker run -d -p 80:80 -name webserver nginx
  • docker stop webserver, docker rm webserver
  • docker pull [選項] [Docker Registery地址] <倉庫名>:<標籤>

    • Docker Registery地址格式: <域名/IP>[:埠號]
    • 倉庫名: <使用者名稱>/<軟體名>
    • docker pull ubuntu:14.04, 即docker pull library/ubuntu:14.04
    • docker run -it --rm ubuntu:14.04 bash
  • docker images, 多層次儲存結構,Union FS

    • docker images -f dangling=true, dangling images!
    • docker rmi $(docker images -q -f dangling=true)
    • docker images -a, docker images ubuntu, docker images ubuntu:16.04
    • docker images -f since=mongo:3.2, docker images -f before=mongo:3.2
    • docker images --filter label=com.example.version=0.1
    • docker images -q, quiet
    • docker images --format "\{\{.ID\}\}: \{\{.Repository\}\}"(實際命令中\不需要), Go的模版語法
      • docker images --format "table \{\{.ID\}\}\t\{\{.Repository\}\}\t\{\{.Tag\}\}"(實際命令中\不需要)
  • docker commit

    • 該命令除了學習之外,還有一些特殊的應用場合,比如被入侵後儲存現場等
    • 該命令意味著所有對映象的操作都是黑箱操作,生成的映象也被稱為黑箱映象
    • docker exec -it webserver bash
    • docker diff webserver
    • docker commit --author "Wenfeng Shi" --message "change the default page\!" webserver nginx:v2
    • docker history nginx:v2
    • docker run --name web2 -d -p 81:80 nginx:v2
  • Dockerfile

    • FROM scratch
    • RUN指令有shell和exec格式,即RUN ["可執行檔案", "引數1", "引數2"]
    • docker build -t nginx:v3 ., .是上下文路徑, 即docker build [選項] <上下文路徑/URL/->
    • .dockerignore檔案
    • docker build https://github.com/twang2218/gitlab-ce-zh.git#:8.16
    • docker build http://server/context.tar.gz
    • docker bulid - < Dockerfilecat Dockerfile | docker build -
    • docker build - < context.tar.gz
    • Dockerfile指令:Dockerfile官方文件, Dockerfile最佳實踐文件
  • 其他

    • 從rootfs壓縮包匯入,docker import http://download.openvz.org/template/precreated/ubuntu-14.04-x86_64-minimal.tar.gz openvz/ubuntu:14.04
    • docker save nginx:v3 | gzip > nginx.v3.tar.gz
    • docker load -i nginx.v3.tar.gz
    • 高階命令docker save <映象名> | bzip2 | pv | ssh <使用者名稱>@<主機名> 'cat | docker load'
  • 刪除

    • docker rmi [選項] <映象1> [<映象2> ...]
      • docker rmi 501, docker rmi centos
    • docker rm [選項] <容器1>
    • docker images --digests
    • 並非所有的 docker rmi 都會產生刪除映象的行為
    • docker rmi $(docker images -q -f dangling=true)
    • docker rmi $(docker images -q nginx)
    • docker rmi $(docker images -q -f before=nginx:v2)

bash FROM nginx RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

  • 對於 CentOS/RHEL 的使用者來說,在沒有辦法使用 UnionFS 的情況下,一定 要配置 direct-lvm 給 devicemapper ,無論是為了效能、穩定性還是空間利用率

使用容器

  • 啟動

    • docker run ubuntu:14.04 /bin/echo 'hello world', docker run -t -i ubuntu:14.04 /bin/bash
    • docker start
    • docker run -d ubuntu:14.04 /bin/sh -c "while true; do ech o hello world; sleep 1; done"
      • docker ps
      • docker logs [container ID or NAMES]
      • docker stop f07
    • 當Docker容器中指定的應用終結時,容器也自動終止, docker ps -a
      • docker start f07, docker restart f07
    • docker run -idt nginx /bin/bash, docker attach f07
    • nsenter
      • PID=$(docker-pid 243c32535da7)
      • sudo nsenter --target 10981 --mount --uts --ipc --net --pid
  • 匯入匯出

    • docker export 7691a814370e > ubuntu.tar 匯出容器快照
    • cat ubuntu.tar | docker import - test/ubuntu:v1.0 匯入映象, 不同於 docker load(包含後設資料資訊和歷史資料)
    • docker import http://example.com/exampleimage.tgz example/imagerepo
  • 刪除

    • docker rm 3fd, docker rm -f 3fd
    • docker rm $(docker ps -a -q)

訪問倉庫

  • DockerHub
    • docker login, docker search node
    • docker search node --filter=stars=38, docker search node --filter=stars=38
    • 可實現自動建立功能(Automated Builds), Dokcer Hub && GitHub && BitBucket
  • 私有倉庫
    • 倉庫會被建立在容器的/tmp/registry, -v引數可將映象檔案存放在本地的指定路徑。
      • docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry
    • docker tag ba58 192.168.7.26:5000/test
    • docker push 192.168.7.26:5000/test
    • config_sample.yml 配置檔案

資料管理

  • docker run -d -P -v /webapp --name web training/webapp python app.py, -v引數用來建立data volume
  • Dockerfile中的VOLUME也可以進行設定
  • docker rm -v ef4 刪除容器時,附帶刪除volume
  • docker run -d -P -v /src/webapp:/opt/webapp/ --name web training/webapp python app.py,掛載主機目錄為資料卷
    • docker run -d -P -v /src/webapp:/opt/webapp/:ro --name web trainging/webapp python app.py 只讀許可權
  • docker inspect web
  • docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash 掛載本地檔案
    • 最簡單的辦法就直接掛載檔案的父目錄
  • data volumes container
    • docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres
    • docker run -d --volumes-from dbdata --name db1 training/postgres
    • docker run -d --volumes-from dbdata --name db2 training/postgres
    • docker run -d --name db3 --volumes-from db1 training/postgres
    • docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata 備份
    • docker run -v /dbdata --name dbdata2 ubuntu /bin/bash 恢復, 建立一個帶有空資料卷的容器
    • docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar 恢復, 解壓到掛載的資料卷容器中
    • docker run --volumes-from dbdata2 busybox /bin/ls /dbdata 恢復,測試

網路

  • 外部訪問容器
    • docker run -d -P nginx, docker ps -l
    • docker logs -f 6ed
    • 引數-p支援的格式有,IP:HostPort:ContainerPort, IP::ContainerPort, HostPort:ContainerPort
    • docker run -d -p 5000:5000 training/webapp python app.py 預設繫結所有介面上的所有地址
    • docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
    • docker port 6ed, docker port 6ed 80 檢視埠對映
    • docker run -d -p 5000:5000 -p 3000:80 training/webapp python app.py 對映多個埠
  • 容器互聯
    • docker run -d -P --name web training/webapp python app.py
    • docker inspect -f "\{\{ .Name \}\}" aed(實際命令中\不需要) 檢視容器名字
    • docker run -d --name db training/postgres 容器互聯
    • docker run -d -P --name web --link db:db training/webapp python app.py, --link引數實現容器互聯
      • --link name:alias, 其中 name 是要連結的容器的名稱, 是這個連線的別名
      • Docker通過2種方式為容器公開連線資訊,即環境變數、/etc/hosts檔案
      • env, cat /etc/hosts, ping db
  • 高階網路配置
    • 待詳細介紹
    • sysctl -w net.ipv4.ip_forward=1
    • iptables -nL, iptables -t nat -nL, brctl show, ip addr show eth0, brctl addbr bridge0
    • docker run -i -t --rm --net=none base /bin/bash
    • docker inspect -f '\{\{.State.Pid\}\}' 1f1f4c1f931a(實際命令中\不需要)
    • 點到點連線
      • ip link add A type veth peer name B
      • ip link set A netns 2989
      • ip link set B netns 3004

安全

  • 核心的名稱空間, 在容器中執行的程式不會被執行在主機上的程式和其它容器發現和作用。(擁有獨立的網路棧)
  • 控制組機制, 實現資源的審計和限制
  • 服務端防護
    • 使用本地的 Unix 套接字機制替代了原先繫結在 127.0.0.1 上的 TCP 套接字
    • 終極目標
      • 將容器的 root 使用者對映到本地主機上的非 root 使用者,減輕容器和主機之間因許可權提升而引起的安全問題
      • 允許 Docker 服務端在非 root 許可權下執行,利用安全可靠的子程式來代理執行需要特權許可權的操作
  • 核心能力機制(capability), 提供細粒度的許可權訪問控制。
    • 容器可以禁用一些沒必要的許可權:
      • 完全禁止任何 mount 操作
      • 禁止直接訪問本地主機的套接字
      • 禁止訪問一些檔案系統的操作,比如建立新的裝置、修改檔案屬性等
      • 禁止模組載入
  • 其他安全特性:TOMOYO, AppArmor, SELinux, GRSEC

底層實現

  • Docker 底層的核心技術包括 Linux 上的名稱空間(Namespaces)、控制組 (Control groups)、Union 檔案系統(Union file systems)和容器格式 (Container format)
  • namespace: pid名稱空間、net名稱空間、ipc名稱空間、mnt名稱空間、UTS("UNIX Time-sharing System") 名稱空間、user 名稱空間
  • cgroups: 對共享資源進行隔離、限 制、審計等
  • UnionFS: 聯合檔案系統是一種分層、輕量級並且高效能的檔案系統
    • 目前支援的聯合檔案系統種類包括 AUFS, btrfs, vfs 和 DeviceMapper。
  • libcontainer: 容器格式 https://github.com/docker/libcontainer
  • Docker 的網路實現其實就是利用了 Linux 上的網路名稱空間和虛擬網路裝置(特別是 veth pair)