Docker初级篇

img

1. docker是什么

  1. docker就是一个容器,可以理解为更进一步的虚拟机。

  2. 理念:Build, Ship and Run Any App, Anywhere.

  3. 网址

    • 官网:https://docker.com/

    • 仓库:https://hub.docker.com/

  4. 基本架构

    Docker 采用了 C/S 架构,包括客户端和服务端。Docker 守护进程 (Daemon)作为服务端接受来自客户端的请求,并处理这些请求(创建、运行、分发容器)。

    客户端和服务端既可以运行在一个机器上,也可通过 socket 或者 RESTful API 来进行通信。


2. docker思想

  1. docker就是一头载着许多集装箱的鲸鱼

  2. 一次镜像,到处运行。

  3. 隔离性:容器之间相互独立,互不相通。

  4. 容器就是进程。

  5. 开发+运维 = Devops,开发运维一体化。

  6. Docker实质上就是在现有系统内制造了一个隔离的文件环境,它的执行效率几乎等同于宿主机。

  7. docker为什么这么快**?**

    因为它是一个极小型的Linux系统,只加载需要的文件,而且容器内的应用直接运行在宿主机的内核上,容器没有自己的内核、也未虚拟我们的硬件系统。

  8. Docker三件套

    1. 镜像 image:一个镜像可以创建多个容器。
    2. 容器 container:创建一个最小化的Linux环境,需要的就加载、不需要的就不加载。
      1. 仓库 repository:存放各种镜像。
  9. 镜像是分层的,里面是UnionFS联合文件系统

  10. 镜像层 与 容器层

  • 镜像层为只读,不可修改
  • 容器层在镜像层之上,可以读写。
<img src="/Users/thinkstu/Library/Application Support/typora-user-images/image-20220324193021492.png" alt="image-20220324193021492" style="zoom: 33%;" />
  1. 默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器

3. 安装

安装方式:1. 官方 2. 我的安装

前提条件:原先未安装Docker

  1. 卸载旧版本
 sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
  1. 官方安装

我采用了yum的阿里源(并非第5条提到的docker阿里源),官方的慢。

#安装gcc
yum -y install gcc
yum -y install gcc-c++

# 安装 yum-utils 包,并设置稳定存储库,目的:提供安装docker的库
yum install -y yum-utils
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
#正式安装docker
yum install docker-ce docker-ce-cli containerd.io
  1. 我的安装

更胜一筹?

学了这么久,我竟然现在才知道踩了一个大坑。yum list中排名第一docker版本是2017年的1.13.1版本。而最新的是2022年的20.10.14版本,我一直用着2017年版的,怪不得好多命令都没有!

#错误的做法,2017版本:yum -y install docker

#正确的做法:安装最新版,ce社区版本
yum -y install docker-ce.x86_64
  1. 配置docker
systemctl start docker
systemctl enable docker
  1. 测试(可省略)
docker run hello-world
  1. docker配置阿里云加速

    • 说明:每位开发者一个账号

    • 登录阿里云 — 控制台 — 容器服务 — 容器镜像服务 — 地址

    • 服务器配置

    sudo mkdir -p /etc/docker
    sudo tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": ["https://xx2ypep6.mirror.aliyuncs.com"]
    }
    EOF
    sudo systemctl daemon-reload
    sudo systemctl restart docker
    

4. 镜像

  1. 概念:
    • 类型:模板
    • 要求:镜像名强制小写
  2. 显示镜像
docker images
#或
docker image ls

镜像名 标签(版本) 镜像id(主键) 创建日期 大小

image-20220324095112805

  1. 搜索镜像
docker search xxx
docker search --limit 5 xxx		#limit默认是25条,不过这里我更愿意用head
---------
docker search xxx |head -6	#但注意:上面这里包括了一行头标题,故-6
  1. 拉取镜像
docker pull 镜像文件名					#默认最新版

docker pull centos		 				#latest
docker pull centos:7.9.2009

镜像版本信息请到官网查看

  1. 删除镜像
docker rmi -f xxx
docker rmi -f $(docker images -qa)		#递归删除全部镜像

4. 镜像进阶

  1. docker tag指令

    docker tag指令标记本地镜像,将其归入某一仓库。

    [root@vm-4-3-centos ~]$ docker tag --help
    
    Usage:  docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
    
    Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
    
    • 其指令是针对镜像,而commit、export是针对容器,完全不一样。
    • 作用:推送至远程仓库时需要tag给镜像备注。
    • docker tag只起标记作用,相当于给镜像重命名、制作硬链接

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rN3LTluK-1651739265985)(https://tva1.sinaimg.cn/large/e6c9d24egy1h0xfv6e7o4j213g04gmy5.jpg)]


5. 容器

容器只要创建了就会存在,即使退出关闭后也可以再次重启。

可使用docker system df查看现容器情况

  1. run容器
docker run -it -p 80:8080 --name="myUbuntu" ubuntu bash

参数说明

-p 8080:80		#小p,指定端口映射:宿主机端口:容器内端口
-P						#大P,系统随机分配端口,Publish all exposed ports to random ports

-d						#后台运行
-i						#interaction,交互模式
-t						#tty,为容器重新分配一个伪输入终端
-it						#常组合使用

--name							#指定容器名称
--privileged=true		#赋予容器root权限,默认不赋予
  1. 退出容器

    1. ctrl + p + q :终端后台挂起

    2. exit:终端销毁(销毁单终端容器,容器暂停)

  2. 再次进入容器

    1. exec:新建终端并进入
    2. attach:返回后台终端
  3. rm 删除容器

    docker rm -f xxx
    #或者
    docker stop xxx
    docker rm xxx
    

    删除所有容器

    docker rm -f $(docker ps -aq)
    
  4. ps指令

    • 说明:单纯的ps指令只能查看当前活着的进程(并非所有)。

    • 使用:

    docker ps
    
    -a		#所有,all
    -l		#最近,latest
    -n 5	#指定数量,number
    -q		#静默模式,queue			只显示容器编号
    

    image-20220324121813823

  5. 启动、重启、停止、强制停止容器

    容器要处于开启状态才能使用

    docker start xxx
    docker restart xxx
    docker stop xxx		#停止
    docker kill xxx		#强制停止
    
  6. 清除所有处于终止状态的容器

    $ docker container prune
    
  7. 容器的名称是唯一的,不可重复。


5. 容器进阶

  1. 容器自动退出机制

    • Docker容器后台运行,就必须有一个前台进程。容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就会自动退出。

    • 例子

      run -d ubuntu之后却发现后台没有存在ubuntu进程 —> 无事可做,已被关闭。

      但是像Mysql、Redis之类的就不会被关闭,因为 —> 还有事可做。

      image-20220324151903595

    • 解决方案:

      ​ 针对Docker中存在着这个机制的问题,我们就只能按照以下三步走

      • 前台启动进程 -it
      • Ctrl+p+q退出
      • docker ps观察是否成功
  2. logs打印容器日志

    docker logs -ft xxx
    -f		# 流输出,即持续输出/类似于Linux下的tail
    -t		# 顺带输出时间戳
    -n		# 指定开始输出的行数,-f可破坏此规则
    

    image-20220324153158897

  3. top查看容器内运行的进程

    docker top xxx
    

    有点长

    image-20220324153542191

    image-20220324153556890

  4. inspect显示容器具体信息

    **结论:**当容器中的所有终端都被关闭时,容器停止运行。(节省资源)

    • 返回一JSON格式信息
    docker inspect xxx
    

    image-20220324154027341


    docker exec xxx bash		#exit退出时,容器自动回归后台
    
  5. diff查看容器内部文件系统变化

    **作用:**查看容器内部文件系统的改动记录

    **说明:**A - Add, D - Delete, C - Change

    但是根据我的观测可能不是特别的准确,比如我在根目录下新增了一文件夹a,这里竟然显示D。然后我又在/a里新建文件夹,显示为A,正常。

    [root@VM-4-3-centos ~]# docker diff --help
    
    Usage:  docker diff CONTAINER
    
    [root@VM-4-3-centos ~]# docker diff 3fe998f421b4
    D /a
    C /run
    D /run/secrets
    C /var/lib/systemd
    A /var/lib/systemd/a.txt
    D /var/lib/systemd/random-seed
    
  6. stats:查看容器占用内存

    docker stats 27dfdb752738
    
  7. docker cp文件复制

    作用:将容器内的文件复制到(备份到)宿主的计算机。

    公式:

    docker cp 容器id:容器内路径 宿主路径
    

    实操

    docker cp 095333dc1a5a:/test/a.txt .
    
  8. commit成新镜像

    慎用commit:https://yeasy.gitbook.io/docker_practice/image/commit

    用作备份还好,当用作制作新镜像就有点糟糕。

    • 思想:将当前容器提交成为新的镜像,产生新的镜像文件(不会覆盖原来的)。

    • 代码:

      #--author 是指定修改的作者,而 --message 则是记录本次修改的内容。
      docker commit -m="" -a=""  容器id  包名/镜像名:版本号
      
      
      docker commit -a="thinkstu" -m="enhance version for vim" \ 
      4ccdf283ef3c thinkstu/ubuntu_vim:1.0.1
      

      image-20220324201118690

  9. 容器完整备份

思想:直接将容器打包成一个tar包,需要的时候再导进。

  • 两种命令

    • 导入:import
    • 导出:export
  • export公式

    docker export xxx > 导出文件名.tar
    
    docker export 095333dc1a5a > ubuntu222.tar
    
  • import公式

    cat 文件名.tar | docker import - 组织名/镜像名:版本号
    
    cat ubuntu222.tar |docker import - thinkstu/ubuntu_test:1.0.1
    
    • 注意事项:
      • 当我们将一个容器完整容器export导出时,它是作为一份镜像被导出
      • 所以当我们import导入一个tar包的时候,我们需要手动的填入一些信息,包名、镜像名、版本号,导入的文件也是一个镜像,而不是容器.
  1. commit与export的理解

    commit是在本地直接将容器打包成镜像的操作,属于提交的类型。

    export指令则先将容器commit成一个新镜像,然后再使用tar将镜像打包导出到宿主机。

    image-20220404090539954

6. 仓库

三种仓库:阿里云、私有云、官方

**推荐:**阿里云(默认私有)、私有云(默认公开)

**不推荐:**官方(默认公开、访问速度慢)

1. 阿里云

阿里云Docker镜像仓库( 个人免费+企业收费 )

阿里云仓库默认私有,只有登录才能下载

可以更改为公共的,让其他人不需要登录就能下载

  • 创建阿里云容器镜像服务、个人实例。

  • 创建命名空间

  • 以命名空间为基础创建仓库

  • 推送至远程仓库

#登录、按要求打包、提交至远程仓库
docker login --username=tb174293514 registry.cn-beijing.aliyuncs.com

docker tag [ImageId] [阿里云地址]/[命名空间]/[镜像重命名]:[镜像版本号]

docker push registry.cn-beijing.aliyuncs.com/thinkstu/uu:1.0

实例

#三段式:登录、打包、上传
docker login --username=tb174293514 \registry.cn-beijing.aliyuncs.com

docker tag 9b495bdf4db2 registry.cn-beijing.aliyuncs.com/thinkstu/ubuntu_vim:1.0.1

docker push registry.cn-beijing.aliyuncs.com/thinkstu/ubuntu_vim:1.0.1

拉取远程仓库的内容:到阿里云仓库中亲自查询再pull方便些

#两段式:登录、拉取
docker login --username=tb174293514 registry.cn-beijing.aliyuncs.com

docker pull registry.cn-beijing.aliyuncs.com/thinkstu/ubuntu_vim:[镜像版本号]
2. 私有云

私有云自搭建之初就是公有的,任何人都可以拉取的到

所以我只要将拉取的链接直接发给别人就好

不过对方主机要先放开对我服务器域名的安全限制,具体做法与下面本机修改安全协议一样

  • 具体思路:利用Dockerz自建仓库( registry ),然后开放端口、配置信息。

  • 搭建私有云服务器

    1. 拉取镜像registry

    2. 运行容器、端口映射

    3. 访问测试(宿主机外网、宿主机内网、docker内网)

    docker pull registry
    
    docker run -d -p 5000:5000 \
    -v ~/myregistry/:/tmp/registry \
    --privileged=true registry
    
    curl -XGET http://42.192.83.9:5000/v2/_catalog
    curl -XGET 10.0.4.3:5000/v2/_catalog
    curl -XGET 172.17.0.1:5000/v2/_catalog
    
    #测试结果:空空如也
    {"repositories":[ ]}     
    
  • 上传镜像至私有云

    1. 修改安全协议

    2. commit提交容器为新镜像

    3. tag 修改镜像格式

    4. 上传push

    提示:如果在第一步就把镜像名规范化,则第二步可以不需要。

    Docker默认不支持http协议,修改配置使push跳过安全机制

    vim /etc/docker/daemon.json
    
    #新增一行,记得在上行加逗号
    																				,
    "insecure-registries": ["172.17.0.1:5000"]
    
    #重启docker服务,使服务生效
    systemctl restart docker
    
    docker commit -m="enhance ubuntu for ifconfig" -a="thinkstu" c4ca8d49a98f myubuntu_ip:1.0.2
    
    #相对于阿里云,这里的命名空间不是必须的
    docker tag [image_id] [私有云地址]/[命名空间]/[镜像重命名]:[镜像版本号]
    docker tag myubuntu_ip:1.0.2 172.17.0.1:5000/myubuntu_ip:1.0.2
    
    docker push 172.17.0.1:5000/mybuntu:1.0.2
    
    #查看是否上传成功
    curl -XGET 172.17.0.1:5000/v2/_catalog
    {"repositories": [
    "mycentos",
    "thinkstu/mycentos",
    "thinkstu/mycentos02"]}
    
  • pull从私有云拉取镜像

    #查看私有云上的软件信息与版本号
    #1. 查看私有云镜像列表
    curl 172.17.0.1:5000/v2/_catalog
    #2. 根据镜像名寻找版本
    curl 172.17.0.1:5000/v2/[镜像全名]/tags/list
    curl 172.17.0.1:5000/v2/thinkstu/mycentos/tags/list
    {"name": "thinkstu/mycentos",
    "tags": [
    "1.2",
    "1.1"]}
    
    docker pull 172.17.0.1:5000/mycentos:1.2
    
3. 官方仓库

上传至官方仓库的镜像默认公开

免费版本只能对设置一个镜像为私有

  1. 官方网站注册账号

  2. 登录账号

  3. 提交镜像

    docker login -u thinkstu
    
    #1.'tag镜像':[地址]/[命名空间]/[镜像重命名]:[镜像版本号]
    docker tag centos04:1.0 thinkstu/centos:9.9
    
    #2. '提交镜像'
    docker push push thinkstu/centos:9.9
    

    这里

    1. 地址可以没有,默认:docker.io/
    2. 命名空间必须是 docker网站的用户名
  4. 拉取镜像

    用户名(命名空间)/镜像名 : 版本号

    push thinkstu/centos:9.9
    #速度也非常的慢
    

    image-20220401122744438

4. 三种方式对比

都源自在官方提供的接口上进行定制化

  1. 登录:阿里云与官方只有登录之后才能进行push操作,否则会提示未授权。
'用法:docker login [OPTIONS] [SERVER]

'阿里云'docker login -u=tb174293514 registry.cn-beijing.aliyuncs.com

'私有云'无需登录

'官方  'docker login -u thinkstu
  1. tag[云地址]/[命名空间]/[镜像重命名]:[镜像版本号],标记镜像、为push做准备。
docker tag 9b495bdf4db2 \
registry.cn-beijing.aliyuncs.com/thinkstu/ubuntu:1.0.1

docker tag 39272891e4b4 \
172.17.0.1:5000/myubuntu_ip:1.0.2

docker tag centos04:1.0 \
thinkstu/centos:9.9
  3. **push**

前提:已登录。

push目标其实由两个因素构成:云地址+命名空间

云地址为产商标识、命名空间可看作用户标识(用户名)

'阿里云'docker push registry.cn-beijing.aliyuncs.com/thinkstu/ubuntu_vim:1.0.1

'私有云'docker push 172.17.0.1:5000/mybuntu:1.0.2

'官方 'docker push thinkstu/centos:9.9
'相当 'docker push docker.io/thinkstu/centos:9.9
  1. pull公有仓库

    直接登录事先存在的仓库地址查看版本信息,然后直接pull。


7. 网络

docker中所有的网络都是虚拟的,转发效率高(内网传递)。

当创建容器时如没有指定网段,则会被分配到默认网段docker0。

默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器。

  1. 原理:veth-pair技术

    veth-pair 就是一对的虚拟设备接口,和 tap/tun 设备不同的是,它都是成对出现的。一端连着协议栈,一端彼此相连着。正因为有这个特性,它常常充当着一个桥梁,连接着各种虚拟网络设备

    每次创建一个新容器的时候,Docker 从可用的地址段中选择一个空闲的 IP 地址分配给容器的 eth0 端口。使用本地主机上 docker0 接口的 IP 作为所有容器的默认网关。

    https://www.cnblogs.com/bakari/p/10613710.html

  2. 宿主机上查看ip信息

    image-20220401150432810

    三个地址:

    • lo:loop,服务器回环地址 127.0.0.1
    • eth0:Ethern 0,以太网第一个网卡接口,腾讯云内网地址10.0.4.3
    • docker0:docker的第一个网卡接口,地址172.17.0.1,为虚拟的路由器,负责转发容器内的网络请求
  3. 容器内查看ip信息

    yum -y install iproute
    

    image-20220401151753430

    两个地址:

    • 容器回环地址
    • eth0@if9:172.17.0.2
  4. docker网络小结:

    1. docker使用的是Linux的桥接
    2. 宿主机是一个Docker容器的网桥docker0。

    img

  5. –link参数说明

    已淘汰,不推荐;

    为什么需要它?

    想让容器之间通过容器名相互ping通,而不是通过内网ip地址;从而解决docker重启后网络地址随机分配的尴尬。

    # 现在 tomcat03可以直接在内部ping通tomcat02,但是反过来不行
    docker run -d -P --name tomcat03 --link tomcat02 tomcat
    
    • 原理:–link指令在run创建这个容器的时候改写了容器内部的/etc/hosts字段,本质就是改写了映射规则,所以03能直接通过名称找到02。
    • **小技巧:**直接查看/etc/hosts文件能看到此容器中的所有映射关系。
  6. 查看docker内部所有的网络配置

    [root@vm-4-3-centos ~]$ docker network --help
    
    Usage:  docker network COMMAND
    
    Commands:
      connect     Connect a container to a network
    ' create      Create a network
      disconnect  Disconnect a container from a network
      inspect     Display detailed information on one or more networks
    ' ls          List networks
      prune       Remove all unused networks
      rm          Remove one or more networks
    
    [root@vm-4-3-centos ~]$ docker network ls
    NETWORK ID          NAME                DRIVER              SCOPE
    df364ea5e865        bridge              bridge              local
    5ef346efe85f        host                host                local
    6b307841d021        none                null                local
    #备注:这里有两列bridge,其中有一列是name名字,另一列是driver驱动类型。
    #			并不一样,这一查看方法
    
    [root@vm-4-3-centos ~]$ docker network inspect df364ea5e865
    #返回JSON字符串
    

    image-20220401164425579

  7. 自定义网络(容器互联)

    取代–link

    网络配置分类 :

    1. bridge:桥接 (默认,自己创建也是用的bridge模式)
    2. none:不配置网络,一般不用
    3. host:和主机共享网络
    4. container:容器网络连通(少用,局限性很大)

    image-20220401173929045

    自定义网络优势:

    docker为我们自定义的网络维护好了对应的关系,会比docker0更优。

    实现思路:

    利用docker network create指令创建属于自己的网络,在后续创建容器时指定容器使用该网络。

    开始自定义网络:
    [root@vm-4-3-centos ~]$ docker network create --help 
    #只列出3参数,其实还有其他的许多
    Usage:  docker network create [OPTIONS] NETWORK
    Options:
    -d --driver      Driver to manage the Network 
       --gateway   IPv4 or IPv6 Gateway for the master subnet
       --subnet  Subnet in CIDR format that represents a network segment
    
    '范例,其中:子网掩码和网关必须配置,--driver默认就是bridge、故可不写。
    docker network create -d bridge --gateway 192.168.0.1 --subnet 192.168.0.0/16 mynet
    
    • 查看我们自定义的网络配置:

      image-20220401175239712

    • 使用我们自定义的网络配置
      docker run -it --name centos-net-01 --net mynet docker.io/centos:7.9.2009
      
    • 查看刚运行起来的centos容器配置

      docker inspect fc2575aa6ea5
      

      image-20220401175641110

    1. 网络互联
    • 解决问题:网络段之间的互联问题,现在tomcat01与tomcat02因为处于不同的网段,所以它两暂时不能ping通。

    image-20220401190910614

    [root@07741f074e88 /]$ ping 192.168.0.2 
    PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
    ^C
    --- 192.168.0.2 ping statistics ---
    13 packets transmitted, 0 received, 100% packet loss, time 12000ms
    # 100% 的丢包率
    
    • 解决思路:我们为 tomcat02 再赋予192.168.0.1段的地址即可。

    • 解释:相当于tomcat02拥有两块网卡,这两个网络段全部把它接入(当然这是虚拟的)。

    • 实现:docker network connect

    connect将一个网段赋于容器中

    [root@vm-4-3-centos ~]$ docker network connect --help
    
    Usage:  docker network connect [OPTIONS] NETWORK CONTAINER
    'Connect a container to a network
    Options:
       --alias 				    Add network-scoped alias for the container
       --help             Print usage
       --ip string        IP Address
       --ip6 string       IPv6 Address
       --link list        Add link to another container (default [])
       --link-local-ip    Add a link-local address for the container
    
    #不需要参数,直接链接
    docker network connect mynet test1
    
    #查看mynet网段中的信息
    docker network ls
    docker network inspect 6afc49097296
    
    #尝试一下现在能否ping成功:成功!
    [root@07741f074e88 /]$  ping 192.168.0.2
    PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
    64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.093 ms
    64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.071 ms
    ^C
    --- 192.168.0.2 ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 1999ms
    rtt min/avg/max/mdev = 0.069/0.077/0.093/0.014 ms
    

    image-20220401191817565

    1. 指定容器ip地址==–ip==

    前提:跟所在网络的配置相符

    docker run -it --name centos-net-01 --net mynet --ip 192.168.22.03 docker.io/centos:7.9.2009
    
  8. docker网络参数说明
  • --net=bridge 这个是默认值,连接到默认的网桥。

  • –net=host告诉 Docker 不要将容器网络放到隔离的命名空间中,即不要容器化容器内的网络。此时容器使用本地主机的网络,它拥有完全的本地主机接口访问权限。容器进程可以跟主机其它 root 进程一样可以打开低范围的端口,可以访问本地网络服务比如 D-bus,还可以让容器做一些影响整个主机系统的事情,比如重启主机。因此使用这个选项的时候要非常小心。如果进一步的使用 --privileged=true,容器会被允许直接配置主机的网络堆栈。

    =host 容器直接与主机共享网络、端口;

  • --net=container:NAME_or_ID 让 Docker 将新建容器的进程放到一个已存在容器的网络栈中,新容器进程有自己的文件系统、进程列表和资源限制,但会和已存在的容器共享 IP 地址和端口等网络资源,两者进程可以直接通过 lo 环回接口通信。

  • --net=none 让 Docker 将新容器放到隔离的网络栈中,但是不进行网络配置。之后,用户可以自己进行配置。

  1. 大写P的映射规则:当使用P(大写的)标记时, Docker 会随机映射一个 49000~49900 的端口

    到内部容器开放的网络端口。(注意其的范围,任意也是有限制的)


8. 数据卷

  1. 数据卷是什么?Volumn,一种数据的备份、共享策略。

  2. 底层理解:硬链接。

  3. 在宿主机与容器中存在着一种现象:两个目录共享一份文件系统。其中,容器中的这个目录是独立于容器本身的UnionFS联合文件系统,所以即使删除该容器,存在于共享目录的文件还是会被保存下来,位于宿主机中。

  4. 作用:

    1. 数据备份:用作容器拷贝的利器。
    2. 共享文件:宿主机与容器之间、容器与容器之间,例如10个redis容器共享一份配置文件。
  5. 数据卷参数-v、–:

可挂载多个volumn

#目录如不存在则新建
docker run -it -v ~/myData:/etc/data -v ~/myBin:/bin  \
--privileged=true  centos
  1. 查看某容器的数据卷路径
docker inspect 容器id

image-20220404152607502

  1. 具名挂载、匿名挂载

数据卷挂载的两种方式

#具名挂载,挂载的路径由用户自定义
docker run -d -v ~/mysql/data:/var/lib/mysql mysql

#匿名挂载:未指定宿主机的挂载地址,默认分配到/var/lib/docker/volumn目录
docker run -d -v /var/lib/mysql
  • 具名挂载说明:实名挂载,指定双方相互挂载的路径。
  • 匿名挂载说明:宿主机匿名、容器实名,在宿主机上随机生成匿名代号。
  1. 查看宿主机上匿名挂载的数据卷
cd /var/lib/docker/volumn
cd ......
cd _data
  1. 查看volumn指令帮助
[root@vm-4-3-centos ~]$ docker volume --help

Usage:  docker volume COMMAND
Commands:
  create      Create a volume
  inspect     Display detailed information on one or more volumes
  ls          List volumes
  prune       Remove all unused volumes
  rm          Remove one or more volumes
  1. 数据卷挂载新需求:只读权限

在多容器共享数据卷时很有用。

  • 容器内只能读,宿主机能读能写。

  • 实现:rw:能读能写(默认值)、ro:read-only只能读

    docker run -d -p 5000:5000  -v /thinkstu/myregistry/:/tmp/registry:ro \
    --privileged=true registry
    
  1. –volumes-from:数据卷继承

便捷实现多个Docker容器之间、宿主机之间数据共享:直接继承即可。

docker run -it --name "myubuntu100" --volumes-from [容器id] \
--privileged=true ubuntu

9. 常用操作

  1. system df查看镜像与容器情况
docker system df

image-20220403220136554

  1. 用完即删
docker run -it --rm tomcat
  1. 不进入容器执行指令
docker run -d centos ls -l
  1. 清除无主的数据卷、无用的镜像、暂停的容器
docker volume prune
docker image prune

docker container prune
#prune , Remove all stopped containers
  1. –restart参数说明
--restart = always | unless-stopped | no | on- failure
  1. 容器退出后自动删除
--rm=true | false			 #容器退出后是否自动删除,不能跟 同时使用
  1. 限制容器的内存使用量
-m, - -memory = 1g		#单位可以是b/k/m/g
  1. run指令等于先执行create指令再执行start指令。
  2. docker -itd操作诠释
#可以让ubuntu这类的系统直接进入后台运行而不真正的退出
docker run -itd ubuntu
  1. 如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时显式使用 docker rm -v

    指令来指定同时删除关联的容器。


8. 日常实践

1. 启用systemd服务

简介:删删删东西,然后build重构。

  • 解决Docker中CentOS镜像无法使用systemd的问题
  • https://developer.aliyun.com/article/688670
  • #直接下载作者制作好的镜像:
# 下载镜像
docker pull 2233466866/centos-systemd
# 通过镜像运行一个名为test的容器
docker run -dit -v /sys/fs/cgroup:/sys/fs/cgroup:ro --name=test --privileged=true 2233466866/centos-systemd
2. 查看系统自启动程序
systemctl list-unit-files
3. Docker安装宝塔
  1. 创建CentOS容器

    docker run -it --restart=always --name baota \
    -p 80:80 -p 443:443 -p 888:888 -p 8888:8888 \
    --privileged=true -v /home/www:/www centos7.9.2009
    
  2. 参数说明

    #容器开机自启
    –restart=always
    
    #映射宝塔主要需要的端口,也可以自己添加如3306等端口
    -p 80:80 -p 443:443 -p 888:888 -p 8888:8888
    
    映射本地的/home/www作为容器的/www目录
    -v /home/www:/www
    
  3. centos内安装宝塔

    yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh
    
  4. 关闭宝塔面板的离线模式(否则处于离线状态、无法访问)

    rm -rf /www/server/panel/data/not_network.pl && bt reload
    
  5. 设置宝塔程序自启动

    注意:编写脚本——方式多样,实现的效果也多样。

4. ubuntu安装vim
  • Docker原生的ubuntu是精简版本,没有携带vim。

  • apt-get指令, 简写:apt

  • 安装

    Docker 镜像在制作时为了精简清除了 apt 仓库信息,因此需要先执行 apt-get update 命令来更新仓库信息。更新信息后即可成功通过 apt-get 命令来安装软件。

    apt update 						#更新索引
    apt -y install vim		#安装vim
    
5.vi与vim

注意:centos与ubuntu中虽然无vim,但是有vi啊,也不是不能编辑!节省空间!

vi a.txt
6. Docker可视化

两种方案:portainer:初级,Rancher:企业。

# 在此,--restart=always总是自启动,除非被docker stop
docker run -d -p 8000:8000 -p 9443:9443 --name portainer \
    --restart=always \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v portainer_data:/data \
    portainer/portainer-ce:2.9.3
7. 正确启动容器的流程
docker start xxid

docker exec -it xxid /bin/bash
8. 授予容器root权限

问题:Docker挂载主机目录访问时出现cannot ope directory : Permission denied

docker run -it --privileged=true centos
9. 容器的宿主机目录

我们查看到docker的容器在宿主机上的存放地点

cd /var/lib/docker/containers/

image-20220327110207741

10. 安装mysql
  1. 存在的问题:

    • 5.7版本中文乱码
    • 数据如何备份
    .# mysql内部查看mysql现阶段字符集
    show variables like 'character%'
    
  2. 解决方案

#1. 数据备份问题

'/var/lib/mysql:		数据
'var/log/mysql:			日志
'etc/mysql/conf.d:	 配置

docker run -d -p 3305:3306 --privileged=true \
-v ~/mysql/log:/var/log/mysql \
-v ~/mysql/data:/var/lib/mysql \
-v ~/mysql/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=123456  --name mysql_test mysql

'-e设置初始参数,这里:mysql初始密码。
#2. 5.7版本中文乱码问题

[root@VM-4-3-centos /]$ vim /thinkstu/mysql/conf/my.cnf

[client]
default_character_set=utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8

#写入以上内容,重启mysql容器服务:docker restart xxx
  1. 后续情境:mysql容器被误删时如何恢复?
#再次新建 Mysql for Docker 容器,使用相同的数据卷映射

docker run -d -p 3306:3306 --privileged=true \
-v /thinkstu/mysql/log:/var/log/mysql \
-v /thinkstu/mysql/data:/var/lib/mysql \
-v /thinkstu/mysql/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=123456  --name mysql mysql:5.7
11. 运行SpringBoot程序

不依赖宝塔,轻量级运行

  1. 宿主机拿到jar包+编写Dockerfile(其中FROM JDK8
FROM java:8 
COPY *.jar /app.jar 
CMD ["--server.port=8080"] 
EXPOSE 8080 
ENTRYPOINT ["java","-jar","app.jar"]
  1. 将以上传至服务器,然后使用docker build 构建成镜像、运行
docker build -t mySpringboot .

**注意:**不要傻乎乎的将构建成的镜像文件上传至公共仓库,这样会被别人盗取的!

12. 取消默认截断

docker中存在着对长字符串默认截断的参数,我们可以禁止它。

docker ps --no-trunc

Docker高级篇

Dockerfile

作用:构建镜像

解释:通过编写指令脚本来构建镜像,可以在镜像构建之初就并入部分操作。

1. 指令诠释

全部大写

FROM						'from	基础镜像'

MAINTAINER			'maintainer 镜像维护者:标签已被淘汰'
LABEL						'label 镜像标签:官方现在推荐使用此标签'
					 
RUN							'run 镜像构建时需要运行的命令'

ADD							'add:添加镜像、压缩包等,提供自动解压功能

WORKDIR					'workdir 镜像默认的工作目录

VOLUMN					'volumn	挂载目录(数据卷)
EXPOSE					'expose 暴露端口

CMD							'command 指定容器启动时运行的指令,只有最后一个会生效
ENTERPOINT			'enterpoint 指定容器启动时运行的指令,可以追加
 
ONBUILD					'onbuild 以当前镜像为基础镜像,构建下一级镜像的时候触发
COPY						'copy 类似ADD,拷贝宿主机文件到镜像,需指定目录
ENV							'enviroment 设置构建时的环境变量(持续到容器时期)
2. 官方centos7

scratch:这个镜像是虚拟的概念,实际并不存在,它表示一个空白的镜像。

FROM scratch
ADD centos-7-x86_64-docker.tar.xz /
LABEL \
    org.label-schema.schema-version="1.0" \
    org.label-schema.name="CentOS Base Image" \
    org.label-schema.vendor="CentOS" \
    org.label-schema.license="GPLv2" \
    org.label-schema.build-date="20201113" \
    org.opencontainers.image.title="CentOS Base Image" \
    org.opencontainers.image.vendor="CentOS" \
    org.opencontainers.image.licenses="GPL-2.0-only" \
    org.opencontainers.image.created="2020-11-13 00:00:00+00:00"
CMD ["/bin/bash"]
3. build 构建镜像

步骤:编写dockerfile脚本文件,build构建centos镜像。

vim dockerfile01

ROM centos:7.9.2009
LABEL\
        com.thinkstu.name="THINKSTU"
ENV file /tmp
WORKDIR $file
RUN yum -y install vim
EXPOSE 8081
CMD /bin/bash
docker build -f dockerfile01 -t centos_02:1.0 .

'命令详解:
'-f   使用本地的dockerfile文件。
		  #如果dockerfile文件名就是dockerfile,则可以不需要此参数进行指定
		  
'-t   指定名称
'最后英文句号"."告诉docker应该在当前目录中寻找dockerfile01文件
4. history指令

**介绍:**可以查看任意镜像的构建历史(即过程)

**作用:**为我们模仿编写dockerfile文件提供便利

docker  history eeb6ee3f44bd 
#输出结果倒序查看,或者利用cat的相反数:tac

docker  history eeb6ee3f44bd | tac
5. 定制化感悟
  1. Dockerfile 中每一个指令都会在镜像中建立一层,Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过 127 层。不要让docker镜像拥有过多层级,使用==&&==削减层级。

    糟糕的写法(五层):

    FROM debian:stretch
    
    RUN apt-get update
    RUN apt-get install -y gcc libc6-dev make wget
    RUN mkdir -p /usr/src/redis
    RUN make -C /usr/src/redis
    RUN make -C /usr/src/redis install
    

    正确的写法(一层):

    FROM debian:stretch
    
    RUN set -x; buildDeps='gcc libc6-dev make wget' \
        && apt-get update \
        && mkdir -p /usr/src/redis
        && make -C /usr/src/redis \
        && make -C /usr/src/redis install \
    
  2. 镜像是多层存储,每一层的东西并不会在下一层真正被删除,只是会被标记为已删除、一直跟随着镜像。因此镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该被及时手动清理掉,否则多层下来镜像臃肿不堪。

    #比如最后执行yum清除缓存操作
    yum clean all
    
  3. 关于build指令构建时的那个小点 " . "

    当构建的时候,用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。

    有些初学者在发现 COPY /opt/xxxx /app 不工作后,于是干脆将 Dockerfile 放到了硬盘根目录去构建,结果发现 docker build 执行后,在发送一个几十 GB 的东西,极为缓慢而且很容易构建失败。那是因为这种做法是在让 docker build 打包整个硬盘,这显然是使用错误。

    原来如此,所以我们才需要在每一次构建时都新建一空白的目录!

  4. Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 systemd 去启动后台服务,容器内没有后台服务的概念。

    对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。

    错误范例:

    #容器中根本就没有systemctl、service这样的概念(但是可以通过一些技巧得到,原此)
    systemctl start nginx
    service nginx start
    

    正确的做法是直接执行 nginx 可执行文件,并且要求以前台形式运行。比如:

    "nginx -g daemon off
    
  5. 数据卷感悟

    1. 在容器中使用数据卷能够提高容器在运行时的读写效率。(此时数据将直接写入宿主机中而不是容器,减少了一层套壳)
    2. 另外,我在编写Dockerfile的时候就可以编写一些匿名的数据卷,这样就不用怕数据的丢失。而且如果我日后有指定数据卷,那么直接指定即可,匿名的将会失效。
    3. 容器内的数据在容器销毁的时候会丢失,但是数据中的不会。

compose

美好情境:一份yml文件,一键部署

  1. 解释性说明

    • 使用yaml文件定义服务
    • 帮助定义和共享多容器应用程序
    • **最大优点:**原先公司启动100个微服务,挨个去启动,现在一键compose部署。
  2. 安装docker compose

    方式1️⃣:/usr/bin目录下

yum -y install docker-compose

#然后刷新配置
source /etc/profile
方式2️⃣:**/usr/local/bin**目录下
sudo curl -L https://download.fastgit.org/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

#然后赋予权限即可
sudo chmod +x /usr/local/bin/docker-compose

​ 说明3️⃣:其本质上就是个二进制的文件。

  1. 运行compose指令
docker-compose up

#参数
-f, --file 指定使用的模板文件,默认为 docker-compose.yml,可以多次指定。
-p, --project-name NAME 指定项目名称,默认将使用所在目录名称作为项目名。
--verbose 输出更多调试信息。

swarm

img


0. 帮助文档

docker --help
docker images --help

范例

#参数有6个,其中两条拥有简写的形式
[root@VM-4-3-centos]$ docker logs --help

Options:
      --details        Show extra details provided to logs
  -f, --follow         Follow log output
      --since string   Show logs since timestamp 
  -n, --tail string    Number of lines to show from the end of the logs 
  -t, --timestamps     Show timestamps
      --until string   Show logs before a timestamp 
                       relative (e.g. 42m for 42 minutes)

Docker

Docker命令图_容器

image-20220406055821695

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐