Docker

 

desktop23.example.com 172.25.254.23

Selinx iptables disabled    rhel7.2版本

 

1.安装

yum install -y docker-engine-1.10.3-1.el7.centos.x86_64.rpm

docker-engine-selinux-1.10.3-1.el7.centos.noarch.rpm

systemctl start docker

 

2.简单命令

docker version# 查看版本信息

docker基础操作_第1张图片 

docker info# 显示docker系统的信息

(1) 容器管理

docker run -it --name vm1 ubuntu bash# 创建容器交互式运行容器

docker ps -a# 查看容器进程

docker attach vm1# 连接容器

docker top vm1# 查看容器状态

docker logs vm1 # 查看容器指令输出 -f 参数可以实时查看

docker inspect vm1 # 查看容器详情

docker stats vm1 # 查看容器资源使用率

docker diff vm1 # 查看容器修改

A:增加的, D:删除的,C:改变的

docker run -d --name vm2 ubuntu bash# 后台运行容器

docker run -d --name vm1 ubuntu bash -c "while true; do echo westos; sleep 1; done"

docker stop vm1 # 停止容器

docker start `docker ps -qa`# 启动所有容器

docker start vm1 # 启动容器

docker kill vm1 # 强制干掉容器

docker restart vm1 # 重启容器

docker pause  vm1# 暂停容器

docker unpause vm1# 恢复容器

docker rm vm1# 删除容器

docker export vm1 > vm1.tar# 导出容器

docker import vm1.tar p_w_picpath# 导入容器为镜像 p_w_picpath

 

 

(2) 镜像管理

镜像用来创建容器,是容器的只读模板,默认可以从 docker hub 上下载。docker 的镜像是增量修改,每次创建新的镜像都会在父镜像上构建一个增量的层,基于 AUFS 技术。

docker search# 查询镜像

docker pull# 拉取镜像

docker push# 推送镜像

docker p_w_picpaths # 查看本地镜像

docker inspect # 查看镜像详情

docker save ubuntu > ubuntu.tar# 导出镜像

docker load -i ubuntu.tar# 导入镜像

docker rmi# 删除镜像

docker commit# 更新镜像

eg:

a)docker commit vm1 test 会多出一个testp_w_picpath,内容=vm1

 

b)端口映射

docker run -d --name vm2 -p 8080:80 nginx 8080--->80

docker run -d -P --name vm3 nginx -P宿主机随机分配端口

 

 

3.逻辑卷

docker run -it --name vm4 -v /tmp/data1:/data1 -v /tmp/data2:/data2:ro rhel7 bash

 

# 建立一个vm4容器,将物理机上的/tmp/data1映射到容器中的/data1/tmp/data2映射到容器中的/data2,并且/data2属于只读。

-v 参数可以重复使用,挂载多个数据卷到容器中,冒号前面的是宿主机的目录(本地目录不存在 docker 会自动创建),冒号后面的是容器中的挂载目录。docker commit 时卷的数据不会被保存。

 

(1)数据卷容器:

docker create --name data -v /tmp/data:/data rhel7 bash

docker run -it --name vm1 --volumes-from=data rhel7 bash

docker run -it --name vm2 --volumes-from=data rhel7 bash

 

eg:

 

docker attach vm1

bash-4.2# cd /data

bash-4.2# touch 111

 

docker attach vm2

bash-4.2# cd /data

bash-4.2# ls

111

bash-4.2# touch 222

 

[root@desktop23 ~]# ls /tmp/data

111 222

 

(2) 先执行命令,执行完后会自动释放容器

docker run --rm rhel7 cat /etc/hosts

 

(3) 备份数据卷:

 

docker run --rm --volumes-from data -v /tmp/backup:/backup ubuntu tar cf /backup/test.tar /data

 

docker run --rm --volumes-from data -v /tmp/backup:/backup rhel7 tar cf /backup/test.tar /data1

# 失败,因为rhel7中没有打包命令

 

4. 重新设置docker0的网络

 

Docker 在启动时会创建一个虚拟网桥 docker0, 容器启动后都会被桥接到 docker0 ,并自动分配到一个 IP 地址

 

systemctl start docker

ip addr show docker0

 

wKioL1e22i6gyndzAAB2ZsAORE4125.png 

 

(1)先删除掉原有docker0

systemctl stop docker

ip link set dev docker0 down

ip addr del 172.17.0.1/16 dev docker0

 

(2)添加新的docker0

ip addr add 172.17.23.0/24 dev docker0

ip link set dev docker0 up

cd /usr/lib/systemd/system

# /usr/lib/systemd/system上的文件一般不做修改,先进行复制

cp docker.service /etc/systemd/system

cd /etc/systemd/system

vim docker.service

docker基础操作_第2张图片 

添加 --bip 172.17.23.1/24

 

systemctl daemon-reload #修改配置文件后,需要重新加载

systemctl start docker

ip addr show docker0

 

wKioL1e22lbjvQ8KAABkGqMYGgk221.png 

 

5.网络类型

(1) bridge ---- 桥接模式 (默认配置方式)

docker run -it --name vm1 ubuntu bash

(2) host ---- 共享物理机上网络的设置 可以直接分享,不用映射,但会有资源抢夺

docker run -it --net=host --name vm2 ubuntu bash

(3) container 使用其他容器的namespace

docker run -it --net=container:vm1 --name vm3 ubuntu bash  

(4) none 容器内部只能使用loopback,没有其他网络资源

可用 --net 指定

docker run -it --net=none --name vm4 ubuntu bash


6.自定义网络(none 网络模式下分配固定 ip

netns 是在 linux 中提供网络虚拟化的一个项目,使用 netns 网络空间虚拟化可以在本地虚拟化出多个网络环境,目前 netns lxc 容器中被用来为容器提供网络。

使用 netns 创建的网络空间独立于当前系统的网络空间,其中的网络设备以及 iptables 规则等都是独立的,就好像进入了另外一个网络一样。

(1) 运行一个新容器

docker stop `docker ps -aq`

docker rm `docker ps -aq`

docker run -it --net=none --name vm1 ubuntu bash

(2) 加一对接口,并启动

ip link add name veth0 type veth peer name veth1

ip link set dev veth0 up

ip link set dev veth1 up

(3) veth0加入docker0

brctl addif docker0 veth0

(4) 查看PID,进入该namespace做链接

docker inspect -f '``.`State`.`Pid`' vm1




    wKioL1e22yTT60OfAAAf6mrhMNg099.png 

cd /proc/18366/ns

ln -s /proc/18366/ns/net /var/run/netns/18366

wKiom1e22yTi8KiTAAA_GJvogOY453.png 

mkdir /var/run/netns

ln -s /proc/18366/ns/net /var/run/netns/18366

ip netns list#查看所有的network namespace

wKiom1e22yTClTjNAAAV9nBVFT0732.png 

(5) 将另外一个接口添加到容器那端

ip link set veth1 netns 18366

ip netns exec 18366 ip link set veth1 name eth0

ip netns exec 18366 ip link set eth0 up

ip netns exec 18366 ip addr add 172.17.23.10/24 dev eth0

(6) 添加路由

ip netns exec 18366 ip route add default via 172.17.23.1

(7) 测试

brctl show

ip addr show docker0

docker attach vm1

ping 172.25.254.0/24 可以ping

 

常用的 namespace 的命令:

1.) 添加一个 namespace

ip netns add [name]

2.) 在 namespace 中启用一个设备

ip netns exec [name] ip link set lo up

3.) 在 namespace 中新加一个设备

ip link set [dev-name] netns [name]

启用:

ip netns exec [name] ip link set [dev-name] up

4.) 查看指定 namespace 中指定设备的参数信息

ip netns exec [name] ip addr show [dev-name] permanent scope global

5.) 为 namespace 中指定设备设置 ip

ip netns exec [name] ip addr add 172.17.23.20/24 dev eth0

6.) 查看所有 network namespace

ip netns list

7.) ping 虚拟机实例

ip netns exec [name] ping 172.17.23.2

 

7.两个container进行访问 (容器间互联)

--link 参数可以在不映射端口的前提下为两个容器间建立安全连接, --link 参数可以连接一个或多个容器到将要创建的容器。

--link 参数的格式为 --link name:alias,其中 name 是要链接的容器的名称,alias 是这个连接的别名。

docker load -i redis.tar

docker run -d --name redis redis

docker run -it --name redisclient --link redis:db redis bash

 

docker基础操作_第3张图片 

docker基础操作_第4张图片 

docker基础操作_第5张图片 


docker attach redisclient


wKiom1e22n_DrDYSAAA3xpHobzE145.png 

 

8.安全权限问题 (eg:修改容器网络)

设置特权级运行的容器:--privileged=true

设置容器白名单:--cap-add

--privileged=true 的权限非常大,接近于宿主机的权限,为了防止用户的滥用,需要增加限制,只提供给容器必须的权限。此时 Docker 提供了权限白名单的机制,使用--cap-add 添加必要的权限。

 

(1) 默认无权限

   docker基础操作_第6张图片




docker inspect vm1

  可看到:

a) privileged = false

wKiom1e23EnyHitTAAAQGocNKbA669.png 

b) capadd = null

wKioL1e23EmDQKuOAAAYQmxanv4255.png 

 

(2) 满权限,可以执行任意操作,但不安全 

   wKiom1e23Y2wBceEAAAcllUH8Ro522.png

  docker基础操作_第7张图片


docker inspect vm2

  可看到:

a) privileged = true

wKioL1e23EnD-RXYAAANZ20u7qo078.png 

b) capadd = null

 

wKiom1e23EnBdItbAAASzrK92Mg352.png 

 

(3) 白名单,添加必要的服务权限 

wKiom1e23bmSB5JZAAAdxeCc38o042.pngdocker基础操作_第8张图片


 docker inspect vm1

可看到:

a) privileged = false

wKioL1e23Erj_uFZAAAL3nR3o6I426.png 

b) capadd = NET_ADMIN

 

wKiom1e23Erj_1WAAAAZZbO40Ps692.png 

 

9.设置自己的镜像 Dockerfile的编写

 

用已经封装好的镜像修改

构建apache

(1) 封装一个已配置好yum源的镜像 test

docker run -it --name vm1 rhel7 bash

#vm1上配好yum

docker commit vm1 test

 

(2) vim /mnt/test/apache/Dockerfile

--->

FROM test# 基础镜像

MAINTAINER wj# 作者信息

ENV HOSTNAME server1# 主机名

EXPOSE 80# 对外链接端口号

RUN yum install -y httpd && yum clean all# 镜像操作命令

CMD ["/usr/sbin/httpd","-D","FOREGROUND"]# 启动命令,默认只能启动一条,启动httpd并打入后台运行

 

     wKiom1e23ofzlc7bAAA74pz8UkE187.png 

 

(3) docker build -t rhel7:apache .# 创建镜像rhel7:apache

docker基础操作_第9张图片 

docker基础操作_第10张图片 

 

(4) docker history rhel7:apache

docker基础操作_第11张图片 

 

(5) 创建容器

a) 编写测试页

vim /mnt/test/apache/index.html

---> hello

 

b) 创建apache容器,映射端口,测试页

docker run -d --name apache -p 8000:80 -v /mnt/test/apache/index.html:/var/www/html/index.html

rhel7:apache

 

c) 访问

curl 172.25.254.23:8000

wKiom1e23ojj06nHAAAYb3jI4CE072.png 

 

 

用基础镜像修改

构建apache

(1)vim /mnt/test/apache/Dockerfile

--->

FROM rhel7

MAINTAINER wj

ENV HOSTNAME server1

EXPOSE 80

COPY dvd.repo /etc/yum.repos.d/dvd.repo 

RUN yum install -y httpd && yum clean all

ADD index.html /var/www/html

CMD ["/usr/sbin/httpd","-D","FOREGROUND"]

                                      

注意:向镜像中添加文件有两种命令:COPY ADD

COPY 命令可以复制本地文件夹到镜像中;ADD 命令支持添加本地的 tar 压缩包到容器中指定目录,压缩包会被自动解压为目录,也可以自动下载 URL 并拷贝到镜像

 

(2)vim /mnt/test/dvd.repo

--->

[dvd]

name=rhel7.0

baseurl=http://172.17.23.1/rhel7.0

gpgcheck=0

enabled=1

 

(3)vim /mnt/test/index.html

--->

Hello,world

 

(4)创建镜像rhel7.0:apache

docker build -t rhel7.0:apache .

    docker基础操作_第12张图片

...

docker基础操作_第13张图片 

 

(5) 创建容器

wKioL1e23x-gz1TtAAA_d6C0ShE965.png 

 

(6) 查看测试页

wKiom1e23x_xDvI1AAAaYN3hpKU001.png 

 

(7) 查看历史

docker基础操作_第14张图片 

 

构建sshd

(1)vim /mnt/test/sshd/Dockerfile

--->

FROM rhel7

MAINTAINER wj

ENV HOSTNAME server2

EXPOSE 22

COPY dvd.repo /etc/yum.repos.d/dvd.repo

RUN echo root:westos | chpasswd

RUN yum install -y openssh-server && yum clean all

RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -q -N ""

RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_ecdsa_key -q -N ""

CMD ["/usr/sbin/sshd","-D"]

 

注意:可以有多条RUN,但只能有一条CMD

    docker基础操作_第15张图片

(2)vim /mnt/test/sshd/dvd.repo

--->

[dvd]

name=rhel7.0

baseurl=http://172.17.23.1/rhel7.0

gpgcheck=0

enabled=1

 

(3)创建镜像 (注意路径)

docker build -t rhel7:sshd .

docker基础操作_第16张图片 

docker基础操作_第17张图片 

 

(4) 创建容器 (注意映射端口,我们只测连接容器,可以先不用)

wKiom1e23__y6JI0AAA-l97uNI0561.png 

 

(5)测试

wKioL1e24ADB72RkAACUuHfeYns261.png 

 

(6)查看历史

docker基础操作_第18张图片 

 

 

 

启动多个服务

CMD 如果只有一个命令,那如果我们需要运行多个服务怎么办呢?最好的办法是分别在不同的容器中运行,通过 link 进行连接

如果一定要在一个容器中运行多个服务可以考虑用 Supervisord 来进行进程管理,方式就是将多个启动命令放入到一个启动脚本中

首先安装 Supervisord

 

(1) vim /mnt/test/super/Dockerfile

--->

FROM rhel7

MAINTAINER wj

ENV HOSTNAME server1

EXPOSE 22 80

COPY dvd.repo /etc/yum.repos.d/dvd.repo

RUN echo root:westos | chpasswd

RUN yum install -y openssh-server httpd supervisor && yum clean all

RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -q -N ""

RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_ecdsa_key -q -N ""

ADD index.html /var/www/html/

COPY supervisord.conf /etc/supervisord.conf

CMD ["/usr/bin/supervisord"]

 

(2) vim /mnt/test/super/dvd.repo

--->

[dvd]

name=rhel7.0

baseurl=http://172.17.23.1/rhel7.0

gpgcheck=0

 

[docker]

name=docker

baseurl=ftp://172.17.23.1/docker

gpgcheck=0

 

 

(3) vim /mnt/test/super/supervisord.conf

--->

[supervisord]

nodaemon=true

 

[program:sshd]

command=/usr/sbin/sshd -D

 

[program:httpd]

command=/usr/sbin/httpd -D FOREGROUND

 

注意:如果有多个服务需要启动可以在文件后继续添 [program:xxx]

 

(4) vim /mnt/test/super/index.html

--->

Hello,world

 

(5) 创建镜像

docker build -t rhel7:super

    docker基础操作_第19张图片 

docker基础操作_第20张图片 

 

(6) 创建容器并测试

docker run -d --name vm1  rhel7:super

docker基础操作_第21张图片 

 

(6) 查看历史

docker基础操作_第22张图片 

 

 

10.Docker仓库

 

无认证方式

 

(1) 默认 docker 仓库远程推送拉取需要 TLS 加密支持,走的是https 协议,如需开启 http 方式,需要做如下修改

 vim /etc/systemd/system/docker.service

   docker基础操作_第23张图片 

添加:

--insecure-registry 172.25.254.23:5000

 

systemctl daemon-reload

systemctl restart docker.service

 

(2) 导入镜像

docker load -i registry:2.3.1

 

(3) 创建容器

docker run -d --name registry -p 5000:5000 -v /opt/registry:/var/lib/registry registry:2.3.1

 

目录 /var/lib/registry 是仓库存放镜像的位置。

 

(4) 推送镜像

docker tag nginx 172.25.254.23:5000/redis:latest 改标签

# docker 镜像的命名规则 172.25.254.23:5000/redis:latest 中,172.25.254.23:5000 表示 Registry 的地址和端口。

 

docker push 172.25.254.23:5000/redis

# 推送镜像到 172.25.254.23:5000 仓库

docker基础操作_第24张图片 

 

docker rmi 172.25.254.23:5000/redis

# 删除本地 nginx 镜像的 TAG

 

docker pull 172.25.254.23:5000/redis

# 拉取镜像到本地 

 

 

认证机制

 

(1) 创建密码

docker run --entrypoint htpasswd registry:2.3.1 -Bbn wj westos > /opt/auth/htpasswd

 

追加一个用户密码

docker run --entrypoint htpasswd registry:2.3.1 -Bbn admin westos >> /opt/auth/htpasswd

 

cat  /opt/auth/htpasswd

wKioL1e24TORWo1UAAB5smQtOQA429.png 

 

(2) 创建镜像

docker run -d -p 5000:5000 --name registry-auth -v /opt/auth:/auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" registry:2.3.1

 

(3) 推送镜像

docker tag nginx 172.25.254.23:500/nginx

docker push 172.25.254.23:500/nginx

 

wKiom1e24TOywJpuAABWcykpWBo139.png 

# 推送失败,没有密码验证

 

docker login 172.25.254.23:5000 #进行密码验证即可

 

 再次推送

docker基础操作_第25张图片 

# 再次推送成功

 

Registry 的配置信息都存储在 Registry /etc/docker/registry/config.yml 文件。最简单的配置方法是直接将修改好的 YAML 配置文件挂载到 Registry 容器中。

如果只修改少数几个配置信息,可以通过设置环境变量来改变,比如修改storage/filesystem/rootdirectory , 只 需 要 使 用 docker run -e 参 数 设 置 相 应 的REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY 变量。

 

 以上操作均来自老师课上所讲