目录

安装

CentOS

  • 常规安装
yum install -y wget

systemctl stop firewalld
systemctl disable firewalld

wget -P /etc/yum.repos.d/ https://download.docker.com/linux/centos/docker-ce.repo

yum install -y docker-ce
  • 安装指定的版本
# 查看安装版本
yum list docker-ce --showduplicates | sort -r

# 安装 Docker CE 的版本 18.03.0
yum install -y docker-ce-18.03.0.ce-1.el7.centos
  • 启动服务
systemctl start docker
systemctl enable docker
systemctl status docker

Ubuntu

apt-get remove docker docker-engine docker-ce docker.io
apt-get install apt-transport-https ca-certificates curl software-properties-common -y
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
apt-get update -y
apt-get install docker-ce -y
docker version
systemctl enable docker
systemctl start docker
systemctl status docker
配置

Docker 配置文件的路径为 /etc/docker/daemon.json。

  • 配置国内 DaoCloud 的源,加速镜像的拉取。
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://d6f11267.m.daocloud.io
systemctl restart docker
常用指令

Docker 的操作主要分为两大类:

  • 镜像操作
  • 容器操作
  • 注册表操作

镜像操作

# 查看本地镜像
docker images

# 搜索仓库的镜像
docker search

# 拉取仓库的镜像
docker pull docker.io/centos

# 利用 DockerFile 创建镜像
docker build <dockerfile>

# 删除已经终止的容器
docker rm
# 可以删除正在运行的容器
docker -f rm 

# 跟据 ID 将镜像保存成一个文件。
docker save <image_id> > <image_name>.tar

# 同时将多个 image 打包成一个文件。
docker save -o images.tar postgres:9.6 mongo:3.4

# 将容器保存成一个文件。
docker export <container_id> > <image_name>.tar

# 从本地将镜像导入
docker load --input centos.tar
# 或
docker load < centos.tar

# 将容器提交为镜像
docker commit <image_name> <container_id>

# 修改镜像标签
docker tag  <OLD REPOSITORY>:<OLD TAG>  <NEW REPOSITORY>:<NEW TAG>

# 将打标签的镜像上传镜像到仓库
docker push <REPOSITORY>:<TAG>

容器操作

# 创建一个容器但不启动它
docker create 

# 创建并启动一个容器
docker run 

# 停止容器运行,发送信号 SIGTERM
docker stop 

# 启动一个停止状态的容器
docker start 

# 重启一个容器
docker restart

# 删除一个容器
docker rm 

# 发送信号给容器,默认为信号 SIGKILL
docker kill 

# 进入到一个正在运行的容器
docker attach 

# 阻塞一个容器,直到容器停止运行
docker wait 

# 显示状态为运行(Up)的容器
docker ps 

# 显示所有容器,包括运行中(Up)的和退出的(Exited)
docker ps -a 

# 深入容器内部获取容器所有信息
docker inspect 

# 查看容器的日志(stdout/stderr)
docker logs 

# 得到 Docker Server 的实时的事件
docker events 

# 显示容器的端口映射
docker port 

# 显示容器的进程信息
docker top 

# 显示容器文件系统的前后变化
docker diff 

# 在容器里执行一个命令,可以执行 bash 进入交互模式
docker exec

注册表操作

  • 创建仓库:
docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry registry
  • 修改配置文件,使之支持 HTTP
# cat  /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://registry.docker-cn.com"],
  "insecure-registries": ["10.0.0.100:5000"]
}
  • 重启生效
 systemctl restart  docker.service

搭建带 basic 认证的仓库:

  1. 安装加密工具
yum install httpd-tools  -y
  1. 设置认证密码
mkdir /opt/registry-var/auth/ -p
htpasswd  -Bbn fanguiju 123456  > /opt/registry-var/auth/htpasswd
  1. 启动 Registry 容器,在启动时传入认证参数
docker run -d -p 5000:5000 -v /opt/registry-var/auth/:/auth/ -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry
  1. 使用验证用户测试
# 登陆用户
$ docker login 10.0.0.100:5000 
Username: fanguiju  
Password: 123456
Login Succeeded

# 推送镜像到仓库
$ docker push <Image ID> 
The push refers to repository [10.0.0.100:5000/clsn/busybox]
4febd3792a1f: Pushed 
1.0: digest: sha256:4cee1979ba0bf7db9fc5d28fb7b798ca69ae95a47c5fecf46327720df4ff352d size: 527

# 认证文件的保存位置
$ cat .docker/config.json 
{
    "auths": {
        "10.0.0.100:5000": {
            "auth": "Y2xzbjoxMjM0NTY="
        },
        "https://index.docker.io/v1/": {
            "auth": "Y2xzbjpIenNAMTk5Ng=="
        }
    },
    "HttpHeaders": {
        "User-Agent": "Docker-Client/17.12.0-ce (linux)"
    }
}
docker run options

–link

在实践中,自然会遇到 2 个容器之间互相访问通信的问题,这个时候就用到了 docker run --link 选项。

docker run --link 可以用来链接 2 个容器,使得 Receiving Container(主动去链接的容器)和 Source Container (被链接的容器)之间可以互相通信,并且 Receiving Container 也可以获取到 Source Container 的一些元数据信息,如:环境变量。

格式

--link <name or id>:alias
# <name or id>:Source Container 的 Name or ID
# alias:Source Container 在 link 下的别名

例子

# Run Source Container
docker run -d --name selenium_hub selenium/hub

# Run Receiving Container
docker run -d --name node --link selenium_hub:hub selenium/node-chrome-debug

Source Container 和 Receiving Container 之间的数据传递可以通过以下 2 种方式:

  1. 更新 /etc/hosts 文件。
  2. 设置环境变量。

更新 /etc/hosts 文件:通过 link 后,Receiving Container: selenium_hub 就可以通过 hostname: selenium_hub/hub 去访问 Source Container: node 了。可见,–link option 指定的 selenium_hub:hub 实际上会成为 Source Container 在 Receiving Container 中的 hostname。

docker exec -it node /bin/bash

seluser@c4cc05d832e0:/$ cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2  hub 1cbbf6f07804 selenium_hub
172.17.0.3  c4cc05d832e0

root@c4cc05d832e0:~# ping selenium_hub
PING hub (172.17.0.2) 56(84) bytes of data.
64 bytes from hub (172.17.0.2): icmp_seq=1 ttl=64 time=0.184 ms
64 bytes from hub (172.17.0.2): icmp_seq=2 ttl=64 time=0.133 ms
64 bytes from hub (172.17.0.2): icmp_seq=3 ttl=64 time=0.216 ms

root@c4cc05d832e0:~# ping hub
PING hub (172.17.0.2) 56(84) bytes of data.
64 bytes from hub (172.17.0.2): icmp_seq=1 ttl=64 time=0.194 ms
64 bytes from hub (172.17.0.2): icmp_seq=2 ttl=64 time=0.218 ms
64 bytes from hub (172.17.0.2): icmp_seq=3 ttl=64 time=0.128 ms

设置环境变量:当使用 --link 时,Docker 会自动在 Receiving Container 内创建一系列与 Source Container 相关的环境变量。这些环境变量的都会以 name or id or alias 为前缀存在。

  • Source Container Dockerfile 中 ENV 标签设置的环境变量。
  • Run Source Container 时,通过选项 -e、–env、–env-file 设置的环境变量。
docker exec -it node /bin/bash

seluser@c4cc05d832e0:/$ env | grep -i HUB_PORT_4444_TCP_
HUB_PORT_4444_TCP_PROTO=tcp          # Source Container 的 Protocol。
HUB_PORT_4444_TCP_ADDR=172.17.0.2    # Source Container 的 IP 地址。
HUB_PORT_4444_TCP_PORT=4444          # Source Container Dockerfile 中定义的 Port。

–cap-add/–cap-drop

Linux 的 Capability 机制允许你将 Root 相关的高级权限划分成为不同的小单元。目前 Docker 默认只会使用到了以下的 Capability:

  • CHOWN
  • DAC_OVERRIDE
  • FSETID
  • FOWNER
  • MKNOD
  • NET_RAW
  • SETGID
  • SETUID
  • SETFCAP
  • SETPCAP
  • NET_BIND_SERVICE
  • SYS_CHROOT
  • KILL
  • AUDIT_WRITE

查看 Capability 清单:

$ pscap

在某些场景下,你也许需要调整 Docker Container 所能够使用到的高级权限特性。例如:你正在构建一个用来执行 ntpd 或 crony 的容器,为此该容器需要能够修改宿主机的系统时间。但由于 Docker Container 默认不具备 CAP_SYS_TIME 特性,就会导致无法工作。

为了应对这种情况,旧版本中,Docker Container 必须以特权模式运行(使用 --privileged 选项),但这会禁用所有宿主机的安全机制。在 Docker 1.3 版本中,新添了 --cap-add 和 --cap-drop 选项。

  • –cap-add:将指定特性添加到容器中。
docker run -d --cap-add SYS_TIME ntpd
  • –cap-drop:将特定特性从容器中移除。
# 容器不会改变任何进程的 UID 和 GID。
docker run --cap-drop SETUID --cap-drop SETGID --cap-drop FOWNER fedora /bin/sh

或者你可以先移除所有特性,然后再需要的添加回去:

docker run --cap-drop ALL --cap-add SYS_TIME ntpd /bin/sh

–user

–user 选项用于指定 Docker Container 使用的 UID 和 GID 启动,这意味着由该进程创建的任何文件也属于 UID 和 GID 的用户。因为 Docker Containers 共享了同一个 Kernel,因此 UID 和 GID 的列表也是相同的,即使 Container 不知道相关的用户名。

docker container run --rm -it \
  -v $(app):/app \                          # Mount the source code
  --workdir /app \                          # Set the working dir
  --user 1000:1000 \                        # Run as the given user
  my-docker/my-build-environment:latest \   # Our build env image
  make assets                               # ... and the command!