5分钟学docker二刷总结-基础

1 导论

1.1 容器技术

分为核心技术,平台技术,支持技术

1.1.1 核心技术

包括容器规范,runtime,容器管理工具,容器定义工具(镜像等),registory,容器os等,此处可略

1.1.1.1 容器规范

有两个规范:runtime spec和image format spec

1.1.1.2 runtime

是容器真正运行的地方,可理解为容器所在的context,或者运行容器的地方

有三种runtime:lxc, runc, rkt

lxc:linux老牌runtime

runc:docker自己开发的,也是docker默认的runtime

rkt:coreos开发的

1.1.1.3 容器管理工具:

lxd,docker engine, rkt cli

lxd是lxc的管理工具

docker engine包含daemon和cli

rkt cli是rkt管理工具

1.1.1.4 容器定义工具

有docker image,dockerfile, aci

1.1.1.5 registory

有docker hub, docker registory, quay.io

1.1.1.6 容器os

和runtime区别?容积更小,速度更快,容ios是专门针对容器的

1.1.2 平台技术

有编排引擎,容器管理平台,基于容器的PaaS

1.1.2.1 容器编排引擎

有docker swarm, kubernete,mesos

dockerswarm:docker开发的编排引擎

kubernetes:google开发的,同时支持docker和coreos容器

mesos:通用编排引擎,与marathon一起提供编排功能

1.1.2.2 容器管理平台

rancher, containership

1.1.2.3 基于容器的paas

1.1.3 容器支持技术

有网络,服务发现,监控,数据管理,日志管理,安全等方面

1.2 安装与运行第一个container

1.2.1 安装

安装略,见文章1 ubuntu18 docker配置与安装 镜像加速配置-CSDN博客

1.2.2 运行第一个container:

docker run -d -p 80:80 httpd

2 容器核心技术

2.1 什么是容器

容器与虚拟机区别?容器不需要guest os

2.2 为什么需要容器

集装箱解决多种场景笛卡尔积

2.3 容器如何工作

2.3.1 docker架构

有client,daemon,registory,image, container

docker daemon只能监听本主机,如何监听其他主机

2.3.2 client

2.3.3 server

2.3.4 image

生成镜像方法 1 从无到有创建 2 利用已有镜像生成 3 从registory下载别人的

3 docker镜像

3.1 镜像内部结构

3.1.1 hello-world最小镜像

docker pull hello-world

hello-world docker file如下

FROM scratch
COPY hello /
CMD ["/hello"]

解析

1 scratch 从头开始创建container

2 copy 将dockerfile所在目录的hello文件复制到镜像的/目录下

3 cmd是运行容器时会执行,可被传入cmd参数覆盖

3.1.2 base镜像

以centos为例探索base镜像

docker pull centos

3.1.2.1 用户层和kernel层

centos估计有200mb左右

思考 为啥centos镜像只有200m? os包括用户层和kernel层,容器用的host的kernel层,容器包含的主要是用户层,不同的linux发行版本区别也主要是用户层的不同,/dev, /bin这些都是用户层的东西

3.1.2.2 base镜像提供最小规模的linux发行版

centos docker file如下

FROM scratch
ADD centos-7-docker.tar.xz /
CMD ["/bin/bash"]

3.1.2.3 支持多种linux os

3.1.3 镜像分层结构

举例说明分层特性,看一个docker file,分层特性也可以从docker pull时的output看出

FROM debian
RUN apt-get install emacs
RUN apt-get install apache2
CMD ["/bin/bash"]

流程:镜像一层一层搭,搭完新一层立即删除临时旧image,下次搭层再用上次创的旧iamge

思考 为什么容器cmd总是/bin/bash?

思考 修改容器其他层会影响到其他层吗?不会,容器层由镜像层和最顶的可写层组成,实际改动的是可写层,镜像层是只读的,实际的改动会在writable层记录

思考 多个层如果存在相同路径文件,实际环境的此文件是哪层的?最上层的

3.2 构建镜像

方法:1 docker commit(用已有容器生成新镜像) 2 dockerfile

3.2.1 docker commit

思考 docker建镜像可commit或dockerfile,为什么不推荐commit?无法批量管理与创容器

流程 创一个container -> 安装软件比如vi -> 保存container为新image(docker commit container_id new_image_name)

3.2.2 dockerfile

3.2.2.1 第一个docker file

FROM ubuntu
RUN apu-get update && apt-get install -y vim

思考 第二行为啥不能分两行些?方便还是不能?不能,层的缓存特性会导致新建容器不执行apt-get update,可能出问题

3.2.2.2 查看分层结构        

3.2.2.3 image缓存特性

docker 会缓存已有的镜像层,构建镜像时如发现缓存的镜像层,就直接使用,不新建,如果发现新层不一样,就会构建

思考 如何不使用缓存?直接每层都让构建?build后加--no-cache

思考 docker什么时候会用到层缓存特性?构建镜像和下载镜像

3.2.2.4 调试dockerfile

思考 如何调试dockefile? dockerfile创建失败时不会删除上次新创建的imgae层,此时可docker run -it image_id进入容器debug

3.2.2.5 dockerfile常用指令

from maintainer copy add env expose volume workdir rum cmd entrypoint 

workdir 进入容器的当前目录位置,如image不存在这个路径会自动创建

3.3 RUN vs CMD vs ENTRYPOINT

3.3.1 shell & exec

思考 为什么推荐使用exec而不是shell?可包含空格等特殊字符

区别:shell默认使用/bin/bash,所以cmd用shell会解析环境变量,但exec默认不使用/bin/bash,不会直接解析环境变量,如需用bash需显示传入

3.3.2 RUN

3.3.3 CMD

dockerfile中的cmd只有最后一个有效;如果docker run传入cmd,则dockerfile中的cmd会被覆盖。如何传入cmd?docker run -it httpd /bin/bash

3.3.4 ENTRYPOINT

每个都会执行,和cmd不同,不会被忽略只保留最后一个

3.4 分发镜像

如何在多个host使用image?1 dockerfile 2 公用repository 3 本地私有repository

3.4.1 为镜像命名

实际不光有名字,还有tag,一般dockerfile build的是latest默认,知识叫latest不代表是最新的tag

docker tag old_tag new_tag_name

3.4.2 使用公共repository

先在docker host登录

docker login -u username

此处仓库的镜像名会用到用户名,所以镜像格式如下:[username]/image:tag,所以如上传,先改名image

如何上传image到共有hub 1 本地登录docker 2 本地改container名,格式为[username]/container:tag 3 docker push [user]/container:tag

3.4.3 本地registry

进步性:1 无需internet 2 docker hub不是全免费 3 安全原因放外网不好

启动:docker run -d -p 5000:5000 -v /myregistry:/var/lib/registry registry:v2

改名,准备将container传到本地registry 名字指的是registry的名字[registry-host]:[port]/user/conta:version

上传镜像 docker push xxx(为上一步改名后的名字)

测试是否可下载镜像 docker pull xxx

3.5 小结

3.5.1 rmi

思考 rmi可以删其他主机和registry 的吗?可以删本host,不可删registry和其他主机的image

思考 一个image有多个tag,什么时候会真正删除image

4 docker容器

4.1 运行容器

4.1.1 如何指定docker启动运行命令

1 cmd 2 entrypoint 3 docker run后追加

4.1.2 长期运行容器

有的容器运行就退出了,如何长期运行?

4.1.2.1 简单粗暴 传入命令无限循环防止退出

docker run ubuntu /bin/bash -c "while true; do sleep 1; done"

会占用一个终端,加 -d后台运行即可

docker创建后分配随机名字,如果想指定container名字,docker run时传入 --name即可

4.1.3 进入容器方法

4.1.3.1 docker attach

docker attach container_id  直接进入container的原终端,不会新开,如果原终端在无限循环,那你啥也干不了

4.1.3.2 docker exec

docker exec -it container_id

4.1.3.3 区别

如上,是否开新终端 docker logs -f container_id可以查看容器启动命令的输出

4.2 stop/start/restart

docker stop container_id

docker kill container_id

docker run -d --restart=[always|on-failure:3]

4.3 pause/unpause

4.4 删除容器

docker rm container_id

也可一次删除多个:docker rm containera_id containerb_id ...   或 docker rm -v $(docker ps -aq -f status=exited)

4.5 state machine状态机

docker run == docker create + docker start

4.6 资源限制

4.6.1 内存限制

docker run -m 200M --memory-swap=300M ubuntu(注意,swap=300-200=100)

docker run -m 200M --memory-swap 300M progirum/stress --vm 1 --vm-bytes 280M

--vm: 一个线程

--vm-bytes: 每个线程分配的内存(vm-bytes比memory-swap小就没事)

4.6.2 cpu限制

docker run --name "containera" -c 1024 --cpu 1

docker run --name "containerb" -c 512 --cpu 1

-c cpu相对优先级,默认为1024

--cpu 设置工作线程数

发生什么:都是一个cpu,所以ps看cpu使用率是66.6,33.3,不会超过100因为一个cpu

4.6.3 block io带宽限制

docker run -it --name "containera" --blkio-weight 500

--blkio-weight 也是相对值

--device-read-bps 限制读某个设备的bps

--device-write-bps 

--device-read-iops 限制读某个设备的iops

何测容器读写速率?进入容器,time dd -if /dev/zero -of test.out         bs=1M count=800 oflag=direct

direct,device-read-bps才能生效

4.7 容器底层技术

主要有cgroup和namespace

4.7.1 cgroup

容器的cpu和内存的限额实际是限制cgroup 如--cpu-share -m -c --memory-swap,这些会以配置文件形式存储,路径为/sys/fs/cgroup/cpu/docker,如cpu-share,会在该路径下的文件cpu.share保存,内容是docker run配置的值

4.7.2 namespace

namespace管理host唯一的全局资源,linux有六种namespace,分别为mount,uts,ipc,pid,network和user

uts让容器拥有自己的hostname,ipc会隔离容器的共享内存和信号量

5 docker网络

docker安装时会在host创三种网络:bridge,host,null

docker network ls

网络可通过docker run --network=none指定

5.1 none

该网络没有任何网卡,即封闭环境

5.2 host

如何查看容器网卡信息?进入容器,ip l

host网络,在容器中可以看到host的网卡,且container hostname也是hostname

优点:直接使用host网络,性能好

缺点:缺少灵活性,需要考虑端口冲突等

5.3 bridge

docker安装时在host会创建一个docker0的linux bridge,容器默认网络会挂在到这里

主机brctl show可查看bridge

创完容器brctl show胡覅先docker0 的interface列多了一个vethxxx,是容器的虚拟网卡挂在到docker0了

进入容器 ip a查看容器网络配置,这里配置看到的网卡和brctl show看到的网卡不是一个网卡,他们是一对网卡

思考 如何查看容器的网段?可以看容器挂在的网络的子网:docker network inspect bridge,bridge子网网关默认是docker0

5.4 user-define网络

docker提供三种user-define网络驱动:bridge,overlay,macvlan。

可手动创建bridge:

docker network create --driver bridge my_net

创建网络时可手动指定子网,通过--subnet和--gateway指定

思考 容器从bridge分配的ip都是默认的,是否可以手动分配?可以,通过--ip指定,注意,只有使用--subnet创建的子网才可以指定容器创建的ip,否则报错

不同网络容器默认无法通信,可手动添加不同网络之间通信

docker network connect net container_id

5.5 容器间通信

容器间可通过IP,DNS,join方式通信

5.5.1 ip通信

同一个网络的容器通信实际是ip通信

5.5.2 DNS通信

DNS即ping的时候用container name而不是ip

注意 只能在user-define的网络使用,就是说默认的bridget无法使用dns

注意 不同网络dns也无法通信

5.5.3 joined通信

可以使两个或多个容器共用一个网络栈

docker run -d -it --name=weba httpd
docker run -d -it --network=container:weba busybox

5.6 容器与外部世界连接

5.6.1 容器访问外部

容器默认可以访问容器外部网络,为啥?

5.6.2 外部世界访问容器内部

主要通过端口映射,端口映射通过docker-proxy,每个有端口映射的container都会开一个docker-proxy进程

 6 docker存储

主要有两种存储:storage driver和data volume

6.1 storage driver

回顾容器分层特性的可写层:1 对容器的改动均会存到容器可写层 2 修改的数据会从镜像曾复制到可写层,然后修改后存入可写层 3 同名文件只会保留最上层的镜像曾中的文件

driver有很多:AUFS、device mapper 、btrfs、OverlayFS、VFS、ZFS、

用哪个driver?一般用linux发行版 推荐的driver

driver适用于无状态的container,比如busybox,运行时修改的数据会存在可写层,可写层会存在driver,容器没了数据就删了,没有持久化存储

6.2 data volume

volume实际是host的文件,可mount,目前好像无法设置volume大小

6.2.1 bind mount

实质是将host已存在目录或文件mount到容器

-v实现mount,若容器此路径不为空,则路径文件会被藏起来,真是使用的是host mount的文件

docker run -d -v <host_path>:<container_path> container
docker run -d -v /htdocs:/usr/local/apache2/htdocs httpd

注意 容器删除后volume不会被删除,即/htdocs不会被删除 

bind mount时还可指定权限:

docker run -d -p 80:80 <host_path>:<container_path>:ro httpd

思考 host mount的路径不存在会发生什么?不存在的路径会被创一个文件夹而不是文件mount给container

局限性:需要显示指定mount的host路径,限制了container移植性

6.2.2 docker managed volume

docker managed volume和bind mount区别是不需要指定host的mount路径,docker会自己找一个目录存container mount的路径,因为docker指定,方便迁移。如果mount point非空,会将东西复制到volume,然后再将volume mount到container

docker run -d -p 80:80 -v <container_path> httpd
docker run -d -p 80:80 -v /usr/local/apache2/htdocs httpd

docker inspect 发现host mount在/var/lib/docker/volume/container_id/下

docker volume看不到bind mount,只能看到docker managed volume,bind mount得通过docker inspect看

6.3 数据共享

6.3.1bind mount & docker managed volume

bind mount & docker managed volume可以实现数据共享

6.3.2 docker cp

docker cp <host_path> container_id:<container_path>
docker cp container_id:<container_path> <host_path>

6.3.3 容器间数据共享

1 多个container bind mount到一个host path

2 volume container

6.4 volume container

专门为别的容器提供volume的容器,其他容器的volume可以用这个volume container

docker create --name vc_data -v ~/htdocs:/usr/bin/apache2/htdocs -v /other/useful/tools busybox
docker run --name web1 -d -p 80 --volume-from vc_data httpd

特点:

1 不必每次bind mount都显示指定路径,已经由volume container实现了

6.5 data-packed volume container

volume container实质是放在host的,是否有数据完全放在container,给其他容器共享的?

data-packed volume container实际是将mount打包到镜像,然后通过docker managed volume给其他容器i共享

FROM busybox:latest
ADD htdocs /usr/bin/apache2/htdocs
VOLUME /usr/bin/apache2/htdocs

6.6 data volume生命周期管理

主要包括备份、迁移、恢复、销毁volume

6.6.1 备份

如果是本地registry,直接定期备份本地registry目录即可

6.6.2 恢复

同上

6.6.3 迁移

如果registry更新,1 先停掉本地registry容器 2 启动新版本registry容器,把老版本registry volume mount到新版本registry

6.6.4 销毁

容器删除不会删除持久化volume

bind mount删除时不会删除volume;docker managed volume删除时,除非docker rm 时带上-v可以删除volume。如果volume还被其他容器mount,则这个volume也无法删除容器时被删除

常用命令

docker history container_id

docket ps

docker rmi image_id

docker run -it -p 80:80 httpd

docker exec -it ...

docker build -t image_name dockerfile_path 

docker tag src_tag_name target_tag_name

docker search

4 docker容器

docker ps -a

docker container ls -a

思考

1.1.1.6 容器os和runtime区别

2.1 容器与虚拟机区别

2.3.1 docker daemon只能监听本主机,如何监听其他主机   /etc/systemd/system/multi-user.target.wants/docker.service,ExecStart环境变量后添加-H tcp://0.0.0.0允许任意ip用户连接

3.1.2 为啥centos镜像只有200m? os包括用户层和kernel层,容器用的host的kernel层,容器包含的主要是用户层,不同的linux发行版本区别也主要是用户层的不同,/dev, /bin这些都是用户层的东西

3.1.2.2 copy add 区别? 如果是归档包,add会直接解压;add支持从url add,copy不支持,

3.1.3 为什么cmd后总是跟/bin/bash? 

3.1.3 修改容器其他层会影响到其他层吗?不会,容器层由镜像层和最顶的可写层组成,实际改动的是可写层,镜像层是只读的,实际的改动会在writable层记录

3.1.3  多个层如果存在相同路径文件,实际环境的此文件是哪层的?为啥?最上层的

3.2.1 docker建镜像可commit或dockerfile,为什么不推荐commit?无法批量管理与创容器

3.2.2 第二行为啥不能分两行写?方便还是不能?不能,层的缓存特性会导致新建容器不执行apt-get update,可能出问题,保证apt-get update是最新的

3.2.2.1 思考 如何不使用缓存?直接每层都让构建?build后加--no-cache

3.2.2.3 docker什么时候会用到层缓存特性?构建镜像和下载镜像,push存或更新镜像的的时

3.2.2.4 如何调试dockefile? dockerfile创建失败时不会删除上次新创建的imgae层,此时可docker run -it image_id进入容器debug

3.3 为什么推荐使用exec而不是shell?可包含空格等特殊字符

3.3.4 cmd和entrypoint区别?1 cmd会被保留仅一个,entrypoint不会,每个都会被执行 2 entrypoint推荐使用,cmd一般用来传入参数,毕竟只能用一次

3.4.2 如何上传image到共有hub 1 本地登录docker 2 本地改container名,格式为[username]/container:tag 3 docker push [user]/container:tag

3.4.2 上传镜像到公共hub会用缓存特性吗?

3.4.2 用registry时注意container名字:公共hub不需要host:port

3.5.1 rmi可以删其他主机和registry 的吗?可以删本host,不可删registry和其他主机的image

3.5.1 一个image有多个tag,什么时候会真正删除image?所有tag都删完的时候

5.2 如何查看容器网卡信息?进入容器,ip l

5.3 如何查看容器的网段?可以看容器挂在的网络的子网:docker network inspect bridge,bridge子网网关默认是docker0

5.4 容器从bridge分配的ip都是默认的,是否可以手动分配?可以,通过--ip指定,注意,只有使用--subnet创建的子网才可以指定容器创建的ip,否则报错

5.4 相同bridget网络容器是否可互通?可互通

5.4 如何实现不同网络容器的通信?需添加容器对某网络的网卡

5.5.2 所有网络都能用dns吗?只有user-define的网络才能用dns

6.2.1 volume是持久化数据,container删除后文件不会被删除

6.2.1  host mount的路径不存在会发生什么?不存在的路径会被创一个文件夹而不是文件mount给container

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值