docker学习笔记

Docker 是一个开源的应用容器引擎,主要利用 linux 内核 namespace 实现沙盒隔离,用cgroup 实现资源限制。
目录:

  • 安装
  • 容器管理
  • 镜像管理
  • 实例
  • 镜像加速
  • 容器的四种网络模式
    • bridge 桥接模式
    • Host 网络模式
    • Container 网络模式:
    • None 网络模式:
  • 容器间互联
  • Dockerfile 编写
    • Dockerfile 常用指令:
    • 将apache服务加入镜像
  • supervisor
  • Docker 仓库
  • 数据卷
  • compose
  • swarm

安装

yum install docker-engine-17.03.1.ce-1.el7.centos.x86_64.rpm   docker-engine-selinux-17.03.1.ce-1.el7.centos.noarch.rpm -y

开启服务

systemctl start docker

容器管理

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 #查看容器修改
docker run -d --name vm1 ubuntu bash -c "while true; do echo westos; sleep 1; done" #后台运行
docker stop vm1 #停止容器
docker start vm1 #启动容器
docker kill vm1 #强制干掉容器
docker restart vm1 #重启容器
docker pause/unpause vm1 #暂停/恢复容器
docker rm vm1 #删除容器
docker export vm1 > vm1.tar #导出容器
docker import vm1.tar image #导入容器为镜像 image

镜像管理

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

docker search #查询镜像
docker pull #拉取镜像
docker push #推送镜像
docker images #查看本地镜像
docker save ubuntu > ubuntu.tar #导出镜像
docker load -i ubuntu.tar #导入镜像
docker commit #更新镜像
docker rmi #删除镜像

实例

开启一个2048游戏容器

docker load -i *.tar
docker images
docker images game2048
docker run -d --name vm1 game2048
docker inspect vm1

docker学习笔记_第1张图片
在浏览器中访问172.17.0.2
docker学习笔记_第2张图片

镜像加速

在https://www.aliyun.com/注册阿里云帐号
在https://cr.console.aliyun.com/cn-hangzhou/mirrors获得自己的镜像加速器地址
配置镜像加速器

vim /etc/docker/daemon.json
{
  "registry-mirrors": ["https://1tade4qz.mirror.aliyuncs.com"]
}
systemctl daemon-reload
systemctl restart docker

直接拉取镜像

docker search nginx

docker学习笔记_第3张图片

docker pull nginx

测试nginx镜像是否可用

mkdir -p /tmp/docker/web
docker run -d --name vm2 -v /tmp/docker/web:/usr/share/nginx/html nginx
vim /tmp/docker/web/index.html

nginx

docker学习笔记_第4张图片
将nginx默认发布页面拷到容器中的另一种方式

docker cp index.html vm2:/usr/share/nginx/html/

容器的四种网络模式

bridge 桥接模式、host 模式、container 模式和 none 模式

启动容器时可以使用 –net 参数指定,默认是桥接模式
以下是 docker 网络初始化的过程
docker学习笔记_第5张图片
docker学习笔记_第6张图片

bridge 桥接模式

docker学习笔记_第7张图片
Bridge 桥接模式的实现步骤主要如下:
(1) Docker Daemon 利用 veth pair 技术,在宿主机上创建两个虚拟网络接口设备,假设为
veth0 和 veth1。而 veth pair 技术的特性可以保证无论哪一个 veth 接收到网络报文,都会将
报文传输给另一方。
(2) Docker Daemon 将 veth0 附加到 Docker Daemon 创建的 docker0 网桥上。保证宿主机的网络报文可以发往 veth0;
(3) Docker Daemon 将 veth1 添加到 Docker Container 所属的 namespace 下,并被改名为 eth0。
如此一来,保证宿主机的网络报文若发往 veth0,则立即会被 eth0 接收,实现宿主机到
Docker Container 网络的联通性;同时,也保证 Docker Container 单独使用 eth0,实现容器网
络环境的隔离性。
bridge 桥接模式下的 Docker Container 在使用时,并非为开发者包办了一切。最明显的是,
该模式下 Docker Container 不具有一个公有 IP,即和宿主机的 eth0 不处于同一个网段。导致
的结果是宿主机以外的世界不能直接和容器进行通信。虽然 NAT 模式经过中间处理实现了
这一点,但是 NAT 模式仍然存在问题与不便,如:容器均需要在宿主机上竞争端口,容器
内部服务的访问者需要使用服务发现获知服务的外部端口等。另外 NAT 模式由于是在三层
网络上的实现手段,故肯定会影响网络的传输效率。

打开一个vm1

docker run -it --name vm1 --volumes-from datavol rhel7 bash

vm1桥接在docker0上
docker学习笔记_第8张图片
停掉vm1

docker stop vm1

桥接断掉
docker学习笔记_第9张图片

Host 网络模式

docker学习笔记_第10张图片
host 模式是 bridge 桥接模式很好的补充。采用 host 模式的 Docker Container,可以直接使用
宿主机的 IP 地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公
有 IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换。当然,
有这样的方便,肯定会损失部分其他的特性,最明显的是 Docker Container 网络环境隔离性
的弱化,即容器不再拥有隔离、独立的网络栈。另外,使用 host 模式的 Docker Container 虽
然可以让容器内部的服务和传统情况无差别、无改造的使用,但是由于网络隔离性的弱
化,该容器会与宿主机共享竞争网络栈的使用;另外,容器内部将不再拥有所有的端口资
源,原因是部分端口资源已经被宿主机本身的服务占用,还有部分端口已经用以 bridge 网
络模式容器的端口映射。

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

docker学习笔记_第11张图片
vm2 的网络环境与宿主机一样

Container 网络模式:

docker学习笔记_第12张图片
(1) 查找 other container(即需要被共享网络环境的容器)的网络 namespace;
(2) 将新创建的 Docker Container(也是需要共享其他网络的容器)的 namespace,使用
other container 的 namespace。
Docker Container 的 other container 网络模式,可以用来更好的服务于容器间的通信。在这种模式下的 Docker Container 可以通过 localhost 来访问 namespace 下的其他容器,传输效率较高。虽然多个容器共享网络环境,但是多个容器形成的整体依然与宿主机以及其他容器形成网络隔离。另外,这种模式还节约了一定数量的网络资源。但是需要注意的是,它并没有改善容器与宿主机以外世界通信的情况。

docker run -it --name vm4 --net container:vm3 ubuntu  #vm4的网络环境与vm3一样

None 网络模式:

网络环境为 none,即不为 Docker Container 任何的网络环境。一旦 Docker Container 采用了
none 网络模式,那么容器内部就只能使用 loopback 网络设备,不会再有其他的网络资源。可以说 none 模式为 Docker Container 做了极少的网络设定,但是俗话说得好“少即是多”,在没有网络配置的情况下,作为 Docker 开发者,才能在这基础做其他无限多可能的网络定制开发。这也恰巧体现了Docker 设计理念的开放。

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

docker学习笔记_第13张图片

netns:
netns 是在 linux 中提供网络虚拟化的一个项目,使用 netns 网络空间虚拟化可以在本地虚拟
化出多个网络环境,目前 netns 在 lxc 容器中被用来为容器提供网络。使用 netns 创建的网络空间独立于当前系统的网络空间,其中的网络设备以及 iptables 规则
等都是独立的,就好像进入了另外一个网络一样。
例如:创建一个test网络

ps ax
cd /proc/15581/ns
ip netns add test
ip netns list
cd /var/run   #查看创建的网络
cd netns/
ls
ip netns del test   #删除网络

docker学习笔记_第14张图片
在 none 网络模式下分配固定 ip:

给容器添加eth0

ln -s /proc/15581/ns/net /var/run/netns/15581
ip netns list
15581
ip link add name veth0 type veth peer name veth1
brctl addif docker0 veth0
ip link set up veth0 #激活veth0
ip link set up veth1 #激活veth1
ip link set veth1 netns 15581 

将 veth1命名为eth0

ip netns exec 15581 ip link set veth1 name eth0

docker学习笔记_第15张图片

给vm4添加ip、网关

ip netns exec 15581 ip link set up dev eth0 #激活eth0
ip netns exec 15581 ip addr add 172.17.0.31/24 dev eth0 #给eth0增加ip
ip netns exec 15581 ip route add default via 172.17.0.1 #给vm4添加网关

现在vm4就可以上网了
docker学习笔记_第16张图片

容器间互联

link 参数可以在不映射端口的前提下为两个容器间建立安全连接, –link 参数可以连接一个
或多个容器到将要创建的容器。
–link 参数的格式为 –link name:alias,其中 name 是要链接的容器的名称,alias 是这个连

 docker run -d --name vm1 -p 8080:80 nginx
 iptables -t nat -nL

这里写图片描述

 docker run -it --name vm2 --link vm1:nginx ubuntu
 root@aa72a211edb9:/# env
root@aa72a211edb9:/# ping nginx

这里写图片描述

Dockerfile 编写

Dockerfile 常用指令:

  1. 指定容器运行的用户
    该用户将作为后续的 RUN 命令执行的用户。比如提供 hadoop 服务的容器通常会使用 hadoop 用户来启动服务。
    命令使用方式,例如使用 shiyanlou 用户来执行后续命令:
    USER shiyanlou

  2. 对外连接端口号
    EXPOSE 命令。
    例如在镜像操作部分增加下面一句:
    EXPOSE 80

  3. 设置容器主机名
    ENV 命令能够对容器内的环境变量进行设置:
    ENV HOSTNAME sevrer1.example.com
  4. 向镜像中增加文件
    向镜像中添加文件有两种命令:COPY 和 ADD。
    COPY 命令可以复制本地文件夹到镜像中:
    COPY website /var/www/html
    ADD 命令支持添加本地的 tar 压缩包到容器中指定目录,压缩包会被自动解压为目录,也可以自动下载 URL 并拷贝到镜像,例如:
    ADD html.tar /var/www
    ADD http://www.westos.org/html.tar /var/www

  5. CMD 与 ENTRYPOINT
    ENTRYPOINT 容器启动后执行的命令,让容器执行表现的像一个可执行程序一样,与CMD 的 区 别 是 不 可 以 被 docker run 覆 盖 , 会 把 docker run 后 面 的 参 数 当 作 传 递 给ENTRYPOINT 指令的参数。Dockerfile 中只能指定一个 ENTRYPOINT,如果指定了很多,只 有 最 后 一 个 有 效 。 docker run 命 令 的 -entrypoint 参 数 可 以 把 指 定 的 参 数 继 续 传 递 给ENTRYPOINT。

  6. 挂载数据卷
    例如将 apache 访问的日志数据存储到宿主机可以访问的数据卷中:
    VOLUME [“/var/log/apche2”]
  7. 设置容器内的环境变量
    ENV

将apache服务加入镜像

vim /tmp/docker/Dockerfile
FROM rhel7
ENV HOSTNAME server1
EXPOSE 80
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y httpd && yum clean all
VOLUME ["/var/www/html"]
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]   #镜像启动命令,默认只能启动一条

配置好yum源

vim /tmp/docker/dvd.repo
[dvd]
name=rhel7.3
baseurl=http://172.25.31.250/rhel7.3
gpgcheck=0

构建镜像 rhel7:v1

docker build -t rhel7:v1 .

docker学习笔记_第17张图片

测试

docker run -d --name vm1 rhel7:v1
docker inspect vm1

docker学习笔记_第18张图片

浏览器访问172.17.0.2,http已开启

docker学习笔记_第19张图片

将ssh服务件如镜像

cd /tmp/docker
mkdir ssh
cd ssh/
vim Dockerfile
FROM rhel7
ENV HOSTNAME server2
EXPOSE 22
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y openssh-server openssh-clients && yum clean all && ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" && ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" && ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" && echo root:westos | chpasswd
CMD ["/usr/sbin/sshd","-D"]

构建镜像

cp ../dvd.repo .
docker build -t rhel7:v2 .

docker学习笔记_第20张图片

测试

docker run -d --name vm2 rhel7:v2
docker ps

这里写图片描述

docker run -it --name vm2 rhel7:v2 bash
bash-4.2# ssh localhost

docker学习笔记_第21张图片

supervisor

CMD 如果只有一个命令,那如果我们需要运行多个服务怎么办呢?最好的办法是分别在不
同的容器中运行,通过 link 进行连接,比如先前实验中用到的 web,app,db 容器。如果一
定要在一个容器中运行多个服务可以考虑用 Supervisord 来进行进程管理,方式就是将多个
启动命令放入到一个启动脚本中。

编辑Dockerfile

vim /tmp/docker/Dockerfile
FROM rhel7
EXPOSE 80 22
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y httpd openssh-server openssh-clients supervisor && yum clean all && ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" && ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" && ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" && echo root:westos | chpasswd
COPY supervisord.conf /etc/supervisord.conf
CMD ["/usr/bin/supervisord"]

配置好yum源

vim /tmp/docker/dvd.repo
[dvd]
name=rhel7.3
baseurl=http://172.25.31.250/rhel7.3
gpgcheck=0

[docker]
name=docker
baseurl=http://172.25.31.250/pub/docker
gpgcheck=0

编辑supervisor配置文件

vim /tmp/docker/supervisord.conf
[supervisord]
nodaemon=true

[program:sshd]
command=/usr/sbin/sshd -D

[program:httpd]
command=/usr/sbin/httpd

构建镜像

cd /tmp/docker/
docker build -t rhel7:v3 .

测试httpd服务和ssh服务是否开启

docker run -d --name vm1 -v /tmp/docker/web/:/var/www/html rhel7:v3
curl 172.17.0.2
ssh -l root 172.17.0.2

docker学习笔记_第22张图片

对写入速度做限制–device-write-bps

docker run --rm -it --device-write-bps /dev/sda:10M ubuntu
root@fb2a9ca40410:/# dd if=/dev/zero of=testfile bs=1M count=100 oflag=direct
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 9.95477 s, 10.5 MB/s
root@fb2a9ca40410:/# 

这里写图片描述

Docker 仓库

Docker 官方已经把仓库封装为镜像,直接通过启动容器就可以部署完成仓库:

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

目录 /var/lib/registry 是仓库存放镜像的位置。除了使用数据卷做镜像存储之外,Registry还支持将镜像存储到 亚马逊的 S3,OpenStack 的 Swift/Glance 等存储后端。

 docker tag nginx localhost:5000/nginx

镜像的命名规则 localhost:5000/nginx 中,localhost:5000 表示 Registry 的地址和端口。

推送镜像到 localhost:5000 仓库

docker push localhost:5000/nginx:latest

docker学习笔记_第23张图片
删除本地 nginx 镜像的 TAG

docker rmi localhost:5000/nginx:latest 

拉取镜像到本地

docker pull localhost:5000/ngin 

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

vim /etc/systemd/system/docker.service
ExecStart=/usr/bin/docker daemon -H fd:// -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
--bip 192.168.0.1/24 --insecure-registry 172.25.31.250:5000
systemctl daemon-reload
systemctl restart docker

vim /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://1tade4qz.mirror.aliyuncs.com"]
  "insecure-registry": ["172.25.31.250:5000"]  #添加这一行
}

默认 docker 仓库远程推送拉取需要 TLS 加密支持,走的是 https 协议
给docker仓库加密

cd /tmp/docker/
mkdir certs
openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key -x509 -days 365 -out certs/domain.crt
docker run -d --restart=always --name registry -v `pwd`/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key -p 443:443 registry:2
docker tag nginx westos.org/nginx
cd /etc/docker/
mkdir -p certs.d/westos.org
cd certs.d/westos.org/
cp /tmp/docker/certs/domain.crt ./ca.crt
docker push westos.org/nginx

给仓库增加认证

cd /tmp/docker/
mkdir auth
docker run --entrypoint htpasswd registry:2 -Bbn wyh westos > auth/htpasswd  #设置用户名和密码
cat auth/htpasswd 

这里写图片描述
若想追加用户名和密码,执行以下命令即可

docker run --entrypoint htpasswd registry:2 -Bbn admin admin >> auth/htpasswd

运行仓库

docker run -d --restart=always --name registry -v `pwd`/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key -v `pwd`/auth:/auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd -p 443:443 registry:2

登陆仓库,上传镜像

docker login -u wyh -p westos westos.org
docker push westos.org/nginx

docker学习笔记_第24张图片
cd .docker/
ls
cat config.json
docker学习笔记_第25张图片

数据卷

docker run 在创建容器时使用 -v 参数可以挂载一个或多个数据卷到当前运行的容器中,-v
的作用是将宿主机上的目录作为容器的数据卷挂载到容器中,使宿主机和容器之间可以共
享一个目录

不指定挂载位置的话容器会自己创建目录挂载

docker run -d --name vm1 -v /usr/share/nginx/html nginx
docker inspect vm1 | grep vol
cd /var/lib/docker/volumes/7c7cbd800d309f3d779b3169c41df72bcd963a8523526510c3ea1001f245c11a/_data
ls

这里写图片描述

编辑Dockerfile文件

mkdir /tmp/docker/test
vim /tmp/docker/test/Dockerfile
FROM rhel7
ADD html.tar /usr/share
VOLUME ["/usr/share/nginx/html"]

因为rhel7镜像中没有/usr/share/nginx/html,所以打包目录用在Dockerfile中用ADD命令添加

mkdir /tmp/docker/test/nginx
mkdir /tmp/docker/test/nginx/html
vim /tmp/docker/test/nginx/html/index.html  #为方便测试编辑一个首页文件
tar -cf html.tar nginx
tar tf html.tar 

docker学习笔记_第26张图片
制作数据卷容器镜像

docker build -t rhel7:v4 .

创建数据卷容器

docker create --name vol rhel7:v4 bash

利用数据卷容器挂载

docker run -d --name vm1 --volumes-from vol nginx

测试

curl 172.17.0.2

compose

编写docker-compose.yml文件

cd /tmp/docker/
mkdir compose
cd compose/
vim docker-compose.yml
apache:
    image: rhel7:v1
    expose:
        - 80
    volumes:
        - ./web:/var/www/html

nginx:
    image: nginx
    expose:
        - 80

haproxy:
    image: haproxy
    volumes:
        - ./haproxy:/usr/local/etc/haproxy
    links:
        - apache
        - nginx
    ports:
        - "8080:80"
    expose:
        - 80

编辑apache首页文件

cp -r web/ compose/

编写haproxy配置文件

cd compose/
mkdir haproxy
vim haproxy/haproxy.cfg
global
    log 127.0.0.1 local0
    log 127.0.0.1 local1 notice
defaults
    log global
    mode http
    option httplog
    option dontlognull
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms
    stats uri /status
frontend balancer
    bind 0.0.0.0:80
    default_backend web_backends
backend web_backends
    balance roundrobin
    server weba apache:80 check
    server webb nginx:80 check

运行

docker-compose up

docker学习笔记_第27张图片

swarm

创建集群

docker swarm init

docker学习笔记_第28张图片
其他节点想要加入集群执行以下命令即可

docker swarm join \
--token SWMTKN-1-24xykxp45mjlfxlbz9b97e7o66ktaci1n23jl0mk5pmg1xqtd6-cc37q5yzqe49ippms760dcity \
172.25.31.1:2377

查看集群

docker node ls

这里写图片描述

让nginx在集群中运行

docker service create --name nginx --publish 80:80 --replicas 3 westos.org/nginx

这里写图片描述
加监控
给自己的私有仓库中加入westos.org/visualizer镜像,在任一节点执行如下命令

docker service create --name=viz --publish=8080:8080/tcp --constraint=node.role==manager --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock westos.org/visualizer

docker学习笔记_第29张图片

为方便测试给每个节点的nginx中加入一个首页

[root@server1 ~]# echo server1 > index.html
[root@server1 ~]# docker container cp index.html nginx.2.n39h34ussexn8669hkz2bq954:/usr/share/nginx/html
[root@server2 ~]# echo server2 > index.html
[root@server2 ~]# docker container cp index.html nginx.3.xrfdd8dqqtbasoa9eyu3v7kq7:/usr/share/nginx/html
[root@server3 ~]# echo server3 > index.html
[root@server3 ~]# docker container cp index.html nginx.1.kkaqglyi1isos87p0lrzxfrki:/usr/share/nginx/html

访问任何一个节点都可以做到负载均衡
docker学习笔记_第30张图片

更新

docker service scale nginx=30 #开启30个nginx集群
docker service update --image westos.org/game2048 --update-parallelism 3 --update-delay 10s nginx #经nginx更新为game2048

docker学习笔记_第31张图片

你可能感兴趣的:(linux-企业级)