04--Docker

前言:前面写过关于Docker+Kubernetes的部署,主要是针对国产化linux系统的适配问题,并没有对docker进行复习。这里整理一下docker的知识点,用作容器化微服务的起点,主要为日常工作配置使用,本章可能有点长,目录我尽量写详细点。

1、概念简介

1.1、容器概念

容器实际上是一种沙盒技术,类似于一个集装箱,可以将你的应用程序"装"起来。这样一来,不同的应用程序之间有了明确的边界,彼此不会相互干扰。被放置在容器中的应用程序可以轻松地被移动和部署。容器的本质是进程,而容器镜像则相当于操作系统中的可执行安装包(".exe")。

1.2、Docker

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。

传统的部署模式是:安装(包管理⼯具或者源码包编译)->配置->运⾏;

Docker的部署模式是:复制->运⾏一次构建多次发布。

Docker重新定义了应用的开发、测试和部署上线过程,核心理念是"一次构建,多次部署"。它支持将应用程序打包成一个可移植的容器,带来以下几点优势:

  1. 标准化应用发布:Docker容器包含了运行环境和可执行程序,可以跨平台和主机使用。
  2. 节约时间:快速部署和启动,相比虚拟机的分钟级启动,Docker容器可以实现秒级启动。
  3. 便于构建微服务架构系统:通过服务编排,能够实现更好的松耦合,方便管理多个微服务。
  4. 节约成本:Docker容器的磁盘空间消耗通常较小,相比传统虚拟机可以大幅减少资源占用,从几个GB级别降低到MB级别。

Docker系统:

  • Docker系统有两个程序:docker服务端和docker客户端
  • Docker服务端:是⼀个服务进程,管理着所有的容器。也叫docker engine
  • Docker客户端:扮演着docker服务端的远程控制器,可以⽤来控制docker的服务端进程
  • Docker服务端和客户端运⾏在⼀台机器上

Docker三大核心组件:

  • Docker 仓库 - Docker registery
  • Docker 镜像 - Docker images
  • Docker 容器 - Docker containers

容器的三⼤组成要素:

  • 名称空间 namespace 容器隔离(pid,net,mnt,user,hostname...)
  • 资源限制 cgroups 资源(内存,cpu)
  • ⽂件系统 overlay2(UnionFS)

2、docker安装

基础环境准备

Centos7,关闭防火墙,关闭selinux,配置阿里基础源,配置epel扩展源

使用yum安装docker

[root@localhost ~]# yum install -y docker

使用命令查看docker版本,发现版本并非最新

[root@localhost ~]# docker -v
Docker version 1.13.1, build 7d71120/1.13.1

docker卸载方式如下

[root@localhost ~]# rpm -qa | grep docker
docker-common-1.13.1-210.git7d71120.el7.centos.x86_64
docker-client-1.13.1-210.git7d71120.el7.centos.x86_64
docker-1.13.1-210.git7d71120.el7.centos.x86_64

[root@localhost ~]# yum remove -y `rpm -qa | grep docker`

    #    这里使用的是反引号取用rpm命令的结果,这样才能卸载干净

CentOS--官⽅安装(非国内网站网速较慢一般不使用)

Docker官⽹:https://www.docker.com/

    #    下载官方源安装
# wget https://download.docker.com/linux/centos/docker-ce.repo
# mv docker-ce.repo /etc/yum.repos.d
# yum install -y docker-ce

    #    下载RPM包安装
# wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-17.09.0.ce-1.el7.centos.x86_64.rpm
# yum localinstall docker-ce-17.09.0.ce-1.el7.centos.x86_64.rpm

国内源安装(正常情况下使用最多的方式)

访问阿里巴巴开源镜像站docker-ce镜像,参考给出的操作手册安装,网站地址如下

docker-ce镜像_docker-ce下载地址_docker-ce安装教程-阿里巴巴开源镜像站

   41  yum install -y yum-utils device-mapper-persistent-data lvm2
   42  yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
   43  sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
   44  yum makecache fast
   45  yum -y install docker-ce
   46  docker -v

此时卸载方式为
[root@localhost ~]# yum remove docker*
这里需要重启

查看历史版本和安装指定版本

    #    查看历史版本
[root@localhost ~]# yum list docker-ce.x86_64 --showduplicates | sort -r
    #    安装指定版本如:
yum install -y --setopt=obsoletes=0 docker-ce-19.03.2 docker-ce-selinux-1
9.03.2

启动检查docker

[root@localhost ~]# systemctl enable docker
[root@localhost ~]# systemctl start docker
[root@localhost ~]# docker -v
[root@localhost ~]# docker version
[root@localhost ~]# docker info
。。。。。。
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
。。。。。。

3、镜像

3.1、基础概念

3.1.1、Docker 仓库

Docker 仓库用来保存镜像,类似于代码控制中的代码仓库。和代码仓库类似,Docker 仓库分为公有和私有两种。

最大的公有的 Docker 仓库名字是 Docker Hub(官方),它提供了庞大的镜像集合供用户使用。这些镜像可以是用户自己创建的,也可以基于别人已有的镜像创建。

私有的 Docker 仓库 则可以是个人或者公司部署的库,用于存储和管理私有的镜像资源。

在 Docker 中,仓库(registry)是顶层的集合,存储了多个仓库(repository)。每个仓库可以包含多个镜像,按照版本(tag)来区分不同的镜像版本,例如 docker.io/centos:7 表示从 Docker Hub 中获取 CentOS 镜像的版本为 7。

国内的 Docker 仓库 包括阿里云、腾讯云、DaoCloud等,用来提供更快速的镜像访问服务,特别是对于国内用户而言,能够显著提高镜像下载的速度。

总结来说,Docker Hub 是全球范围内的 Docker 镜像公共仓库,而私有仓库则提供了安全、私密的镜像管理和存储解决方案

3.1.2、Docker 镜像

Docker 镜像是 Docker 容器运行时的只读模板,由一系列层(layers)组成。Docker 使用 UnionFS(联合文件系统)将这些层联合到单独的镜像中。这种设计使得 Docker 极为轻量级。

当你修改一个 Docker 镜像,比如升级某个程序到新版本时,会创建一个新的层。因此,不需要替换整个原先的镜像或重新构建(这在使用虚拟机时常见),只是添加或升级了一个新的层。

在 Docker 的术语中,一个只读层被称为镜像,镜像是永久不会改变的。由于 Docker 使用统一的文件系统,镜像本身是无状态的,因为镜像不可写入。

镜像本身是由⼀层⼀层的镜像合在⼀起的,如上图,最底层的镜像我们称为基础镜像,在这个基础镜像的基础 上还可以在做镜像,在做的镜像称为⼦镜像,对于⼦镜像来讲在谁的基础之上做的就是⽗镜像。

**镜像 ID:**所有的 Docker 镜像都使用一个 64 位的十六进制字符串来唯一标识。为了方便使用,可以使用这个字符串的前 12 个字符作为短ID,在命令行中使用。然而,由于短ID存在碰撞的可能性,因此服务器通常返回完整的 64 位长ID。

简而言之,镜像的完整ID是64位长的唯一标识符,而为了方便使用,可以使用其前12个字符作为短ID,尽管短ID有可能发生冲突。

Docker 容器和⽂件夹很类似,⼀个Docker容器包含了所有的某个应⽤运⾏所需要的环境。每⼀个 Docker 容器都是从 Docker 镜像创建的。Docker 容器可以运⾏、启动、停⽌、移动、删除、暂停(挂 起)。每⼀个 Docker 容器都是独⽴和安全的应⽤平台,Docker 容器是 Docker 的运⾏⼀部分。

列出当前系统中所有的 Docker 镜像

[root@localhost ~]# docker images
[root@localhost ~]# docker image list
    #    两条命令效果完全相同

输出结果如下

  • REPOSITORY: 镜像的仓库名,通常是由镜像的作者定义的。
  • TAG: 镜像的标签,标识了镜像的特定版本或者变体。
  • IMAGE ID: 镜像的唯一标识符,通常是一个长字符串。
  • CREATED: 镜像创建的时间。
  • SIZE: 镜像的大小。

3.2、镜像管理

24年初很多国内镜像源关闭或停止注册,除可以使用科学上网法外,这里使用配置国内云镜像加速地址的方式进行拉取,配置方式如下:

配置/etc/resolv.confdns解析地址为8.8.8.8后
[root@localhost ~]# vim /etc/docker/daemon.json 
[root@localhost ~]# cat /etc/docker/daemon.json 
{
  "registry-mirrors": [
          "https://ox288s4f.mirror.aliyuncs.com",
          "https://registry.docker-cn.com",
          "http://hub-mirror.c.163.com",
          "https://mirror.ccs.tencentyun.com"
  ]
}
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl restart docker

重启docker后拉取镜像

1)搜索镜像

[root@localhost ~]# docker search tomcat
#查找 star 数⾄少为 100 的镜像,默认不加 s 选项找出所有相关 centos 镜像: 
[root@docker-server ~]# docker search tomcat -f stars=100

2)拉取镜像

[root@localhost ~]# docker pull tomcat
Using default tag: latest
latest: Pulling from library/tomcat
0e29546d541c: Pull complete 
9b829c73b52b: Pull complete 
cb5b7ae36172: Pull complete 
6494e4811622: Pull complete 
668f6fcc5fa5: Pull complete 
dc120c3e0290: Pull complete 
8f7c0eebb7b1: Pull complete 
77b694f83996: Pull complete 
0f611256ec3a: Pull complete 
4f25def12f23: Pull complete 
Digest: sha256:9dee185c3b161cdfede1f5e35e8b56ebc9de88ed3a79526939701f3537a52324
Status: Downloaded newer image for tomcat:latest
docker.io/library/tomcat:latest

    #    不指定版本默认下载最新版

[root@localhost ~]# docker pull mysql:8.0
8.0: Pulling from library/mysql
72a69066d2fe: Already exists 
93619dbc5b36: Already exists 
99da31dd6142: Already exists 
626033c43d70: Already exists 
37d5d7efb64e: Already exists 
ac563158d721: Already exists 
d2ba16033dad: Already exists 
688ba7d5c01a: Pull complete 
00e060b6d11d: Pull complete 
1c04857f594f: Pull complete 
4d7cfa90e6ea: Pull complete 
e0431212d27d: Pull complete 
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709
Status: Downloaded newer image for mysql:8.0
docker.io/library/mysql:8.0


    #    指定版本拉取镜像

3)查看镜像详细信息

    #    查看镜像详细信息
[root@docker-server ~]# docker image inspect 镜像id/镜像名称
[root@docker-server ~]# docker inspect 镜像id/镜像名称

4)删除镜像

#删除⼀个或多个,多个之间⽤空格隔开,可以使⽤镜像名称或id
[root@docker-server ~]# docker rmi daocloud.io/library/mysql
或者
[root@docker-server ~]# docker rmi 81debc
#参数解释:
#rm Remove one or more containers ---移除⼀个或多个容器
#rmi Remove one or more images ---删除⼀个或多个镜像

5)强制删除镜像(工作中不要用)

#如果镜像正在被使⽤中可以使⽤--force强制删除 
# docker rmi docker.io/ubuntu:latest --force
-f, --force Force removal of the image
#注意: 容器运⾏中不能删除,将容器停⽌后,删除容器在删除镜像。

6) 只查看所有镜像的id(这个是和清空镜像连用)

[root@docker-server ~]# docker images -q
98ebf73aba75
81debc95563d
d0957ffdf8a2

7)清空所有镜像

[root@docker-server ~]# docker rmi $(docker images -q)

8)查看镜像制作过程

[root@docker-server ~]# docker history nginx 
#使⽤镜像名或者镜像ID都可以

3.3、阿里云镜像仓库搭建

访问阿里云首页搜索容器镜像服务,个人版免费

按步骤创建自己的镜像仓库方便日后工作中使用,操作过程有详细教程,或按照提示操作即可,这里略过,腾讯云与之相同

4、容器

4.1、基础概念

使用命令创建一个docker容器,它会在所有的镜像层之上增加⼀个可写层。这个可写层有运⾏在CPU上的进程,⽽且有两个不同的状态:运⾏态(Running)和退出态 (Exited)。这就是Docker容器。当我们使⽤docker run启动容器, Docker容器就进⼊运⾏态,当我们停⽌Docker容器时,它就进⼊退出状态。

当我们有⼀个正在运⾏的Docker容器时,从运⾏态到停⽌态,我们对它所做的⼀切变更都会永久地写到 容器的⽂件系统中。要切记,对容器的变更是写⼊到容器的⽂件系统的,⽽不是写⼊到Docker镜像中的。我们可以⽤同⼀个镜像启动多个Docker容器,这些容器启动后都是活动的,彼此还是相互隔离的。 我们对其中⼀个容器所做的变更只会局限于那个容器本身。如果对容器的底层镜像进⾏修改,那么当前正在运⾏的容器是不受影响的,不会发⽣⾃动更新现象。

4.2、容器管理

1)使用镜像运行一个容器,进入容器内部后退出并删除新创建的容器

bash 复制代码
[root@localhost ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
nginx        latest    605c77e624dd   2 years ago   141MB
tomcat       latest    fb5657adc892   2 years ago   680MB
mysql        5.7       c20987f18b13   2 years ago   448MB
mysql        8.0       3218b38490ce   2 years ago   516MB
ubuntu       latest    ba6acccedd29   2 years ago   72.8MB

[root@localhost ~]# docker run -it nginx /bin/bash
-it: 这两个选项结合起来,表示创建一个交互式的容器。具体含义如下:
    -i, --interactive: 保持标准输入 (stdin) 打开,即使没有附加到容器上。
    -t, --tty: 分配一个伪终端 (pseudo-tty)。这使得我们可以与容器的 shell 进行交互。
root@33f13d113201:/# exit
exit

[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                   CREATED          STATUS                      PORTS     NAMES
33f13d113201   nginx     "/docker-entrypoint...."   27 seconds ago   Exited (0) 17 seconds ago             wizardly_ramanujan


#如果你在执⾏docker run时没有指定--name,那么⾃动⽣成⼀个随机字符串

[root@localhost ~]# docker rm wizardly_ramanujan
wizardly_ramanujan

[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

2)创建新容器但不启动

bash 复制代码
[root@localhost ~]# docker create -it nginx /bin/bash

3)容器自启动

bash 复制代码
[root@docker-server ~]# docker run -it --restart=always nginx /bin/bash

--restart=always: 指定容器的重启策略为始终重启。这意味着当 Docker 引擎重启时,该容器会自动重新启动。

4)自销毁容器(没用过)

bash 复制代码
--rm: 默认情况下,每个容器在退出时,其文件系统会保留下来,这样可以保存容器产生的数据。然而,有时你可能只需要临时运行一个容器,而不需要保留其产生的数据。这时就可以使用 --rm 参数。

[root@docker-server ~]# docker run -it --rm nginx /bin/bash
root@be2d0a462ce1:/# exit
exit
此时查看容器无法找到刚创建的容器

注意:不能使用 -d 参数与 --rm 和 --restart=always 冲突。

5)容器命名

bash 复制代码
--name: 为容器分配一个名称。如果不指定名称,Docker 会自动分配一个随机的名称给容器。

示例:
[root@docker-server ~]# docker run -it --name my-nginx-name1 nginx /bin/bash

6)退出容器

bash 复制代码
这里退出容器有两种方法

一种是exit
一种是ctrl+p+q(摁着ctrl摁一下p摁一下q)

建议使用ctrl+p+q,exit推出可能会影响容器状态

7)查看容器

bash 复制代码
1、只查看运行状态的容器:

docker ps

这条命令用于列出当前正在运行的 Docker 容器。


2、查看所有容器(包括停止的)

docker ps -a

使用 -a 参数可以列出所有状态的 Docker 容器,包括运行中的和已停止的。


3、只查看所有容器的 ID:

docker ps -a -q

8)停止/删除所有容器

bash 复制代码
docker stop `docker ps -a -q`
docker rm `docker ps -a -q`

9)查看容器详细信息

bash 复制代码
[root@docker-server ~]# docker inspect 容器名称/容器ID

#经常查看的参数
id号
Networks网络模式
IPAddress ip地址

10)启动容器

bash 复制代码
[root@docker-server ~]# docker start name

11)关闭容器

bash 复制代码
[root@docker-server ~]# docker stop name
[root@docker-server ~]# docker kill name --强制终⽌容器

12)删除容器

bash 复制代码
要删除一个容器,可以使用其容器 ID 或名称。例如:

# docker rm my-container

如果容器正在运行,需要先停止它然后再删除。可以使用 `-f` 参数强制删除容器,但这样可能会导致数据丢失或其他不良影响,因此慎用:

# docker rm -f my-container

13)状态管理

bash 复制代码
删除所有已停止的容器:

docker rm $(docker ps -qf status=exited)

通过 docker ps 和 docker rm 命令,删除所有状态为已停止 (exited) 的容器。

docker ps -qf status=exited: 使用 docker ps 命令配合 -q 参数来仅输出容器 ID,并结合 -f 参数来过滤状态为 exited 的容器。

docker rm $(...): 将 docker ps 输出的容器 ID 作为参数传递给 docker rm 命令,从而删除这些容器。

暂停与恢复

  • pause: 暂停容器内所有的进程,使得容器内的所有活动都暂时停止。
  • unpause: 恢复容器内因 pause 操作而暂停的进程,使得容器内的活动可以继续进行。
bash 复制代码
[root@docker-server ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                   CREATED          STATUS          PORTS     NAMES
8949f10e895a   nginx     "/docker-entrypoint...."   23 minutes ago   Up 23 minutes   80/tcp    nginx1

[root@docker-server ~]# docker pause nginx1
nginx1

[root@docker-server ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                   CREATED          STATUS                   PORTS     NAMES
8949f10e895a   nginx     "/docker-entrypoint...."   24 minutes ago   Up 24 minutes (Paused)   80/tcp    nginx1

[root@docker-server ~]# docker unpause nginx1
nginx1

[root@docker-server ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                   CREATED          STATUS          PORTS     NAMES
8949f10e895a   nginx     "/docker-entrypoint...."   24 minutes ago   Up 24 minutes   80/tcp    nginx1

14)重启容器

bash 复制代码
[root@docker-server ~]# docker restart name

15)容器后台运行

bash 复制代码
[root@docker-server ~]# docker run -dit 镜像ID /bin/bash

-d 后台运⾏必须要加-it

16)容器重命名

bash 复制代码
[root@docker-server ~]# docker rename 老名字 新名字

17)容器资源使⽤统计

bash 复制代码
[root@docker-server ~]# docker stats

18)连接容器

bash 复制代码
1)
docker attach 容器id #前提是容器创建时必须指定了交互shell

2)
1.交互型任务:
[root@docker-server ~]# docker exec -it 容器id /bin/bash

2.后台型任务:不进⼊容器⾥⾯执⾏命令
[root@docker-server ~]# docker exec 容器id touch /testfile

19)容器运行监控

可以使⽤logs、top、wait这些⼦命令

可以通过使⽤docker logs命令来查看容器的运⾏⽇志,其中--tail选项可以指定查看最后⼏条⽇ 志,使⽤-f选项可以跟踪⽇志的输出,直到⼿动停⽌

bash 复制代码
[root@docker-server ~]# docker logs -f nginx2
    #    来查看容器的运⾏⽇志
[root@docker-server ~]# docker top nginx2
    #    显示⼀个运⾏的容器⾥⾯的进程信息

wait打印出容器的退出码

bash 复制代码
打开两个终端窗口
第一个终端窗口
[root@docker-server ~]# docker wait nginx1
此时这个命令会占用此窗口

第二个终端窗口
[root@docker-server ~]# docker stop nginx1
这个命令执行结束后返回第一个窗口查看

[root@docker-server ~]# docker wait nginx1
0

20)宿主机和容器之间相互拷⻉⽂件/⽬录

bash 复制代码
从容器拷贝到本机

假设有一个正在运行的容器,其容器名为nginx1,需要将容器中的文件 /app/data.txt 拷贝到本机的 /home/user/data/ 目录下:

docker cp nginx1:/app/data.txt /home/user/data/

这条命令将容器中的 /app/data.txt 文件复制到本机的 /home/user/data/ 目录下。



从本机拷贝到容器

假设当前目录下有一个名为 config.json 的文件,需要将该文件复制到正在运行的容器nginx1的 /etc/config/ 目录下:

docker cp config.json webapp:/etc/config/

这条命令将本地的 config.json 文件复制到容器nginx1的 /etc/config/ 目录下。


拷贝目录
[root@docker-server ~]# docker cp -a /opt nginx2:/usr/local/bin/ 

4.3、容器镜像打包迁移

容器的打包迁移方式有两种

1)先打包,再转化为镜像

bash 复制代码
[root@docker-server ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                   CREATED          STATUS          PORTS     NAMES
fa433a15b7d7   nginx     "/docker-entrypoint...."   40 minutes ago   Up 15 minutes   80/tcp    nginx2
8949f10e895a   nginx     "/docker-entrypoint...."   3 hours ago      Up 15 minutes   80/tcp    nginx1

[root@docker-server ~]#  docker export -o nginx1_1.tar 8949f10e895a
  
[root@docker-server ~]# docker export nginx2 > nginx2_1.tar

[root@docker-server ~]# ls -ll
总用量 281308
-rw-------. 1 root root      1347 6月  18 19:49 anaconda-ks.cfg
-rw-------  1 root root 144025600 8月   1 21:30 nginx1_1.tar
-rw-r--r--  1 root root 144025600 8月   1 21:35 nginx2_1.tar

选一个包复制过去
[root@docker-server ~]# scp nginx1_1.tar 192.168.188.129:/root/

到129主机上

bash 复制代码
[root@localhost ~]# ls
anaconda-ks.cfg  nginx1_1.tar
[root@localhost ~]# docker import nginx1_1.tar nginx:v1996
sha256:49652cb2ce40b2838496863bfa0f85dc0b232ca3401fc1cab1499dc801198aa1

    #    版本号瞎写的,防止混淆,工作环境严格遵守命名规则

[root@localhost ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
nginx        v1996     49652cb2ce40   8 seconds ago   140MB

容器包成功转化为另一个主机镜像,后续启动容器过程略

2)先保存为本地镜像

在128主机上

bash 复制代码
#本机初始镜像
[root@docker-server ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
nginx        latest    605c77e624dd   2 years ago   141MB
tomcat       latest    fb5657adc892   2 years ago   680MB
mysql        5.7       c20987f18b13   2 years ago   448MB
mysql        8.0       3218b38490ce   2 years ago   516MB
ubuntu       latest    ba6acccedd29   2 years ago   72.8MB

#本机运行的容器
[root@docker-server ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                   CREATED          STATUS          PORTS     NAMES
fa433a15b7d7   nginx     "/docker-entrypoint...."   55 minutes ago   Up 29 minutes   80/tcp    nginx2
8949f10e895a   nginx     "/docker-entrypoint...."   3 hours ago      Up 29 minutes   80/tcp    nginx1

#将容器转化为镜像
[root@docker-server ~]# docker commit nginx2 nginx:v2024
sha256:61d0976fbf6fb3771f178b7c70397e52ad61e814baf9d3b7fb32414684356959
    #    使用commit命令时有以下参数可以使用

    #    -m 添加注释

    #    -a 作者 

    #    -p,--pause=true 提交时暂停容器运⾏



#再次查看本机镜像
[root@docker-server ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
nginx        v2024     61d0976fbf6f   3 seconds ago   141MB
nginx        latest    605c77e624dd   2 years ago     141MB
tomcat       latest    fb5657adc892   2 years ago     680MB
mysql        5.7       c20987f18b13   2 years ago     448MB
mysql        8.0       3218b38490ce   2 years ago     516MB
ubuntu       latest    ba6acccedd29   2 years ago     72.8MB

#使用save将镜像打包然后scp拷贝到129上
[root@docker-server ~]# docker save -o nginx2_1.tar nginx:v2024
[root@docker-server ~]# ls -ll
总用量 283152
-rw-------. 1 root root      1347 6月  18 19:49 anaconda-ks.cfg
-rw-------  1 root root 144025600 8月   1 21:30 nginx1_1.tar
-rw-------  1 root root 145912832 8月   1 21:51 nginx2_1.tar
[root@docker-server ~]# scp nginx2_1.tar 192.168.188.129:/root/
root@192.168.188.129's password: 
nginx2_1.tar                                                         100%  139MB  44.4MB/s   00:03    
[root@docker-server ~]#

到129主机上

bash 复制代码
[root@localhost ~]# docker load < nginx2_1.tar 
2edcec3590a4: Loading layer  83.86MB/83.86MB
e379e8aedd4d: Loading layer     62MB/62MB
b8d6e692a25e: Loading layer  3.072kB/3.072kB
f1db227348d0: Loading layer  4.096kB/4.096kB
32ce5f6a5106: Loading layer  3.584kB/3.584kB
d874fd2bc83b: Loading layer  7.168kB/7.168kB
bb48ecfe0df4: Loading layer  9.216kB/9.216kB
Loaded image: nginx:v2024

[root@localhost ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
nginx        v2024     61d0976fbf6f   10 minutes ago   141MB
nginx        v1996     49652cb2ce40   17 minutes ago   140MB

5、Dockerfile

Docker 提供了⼀种更便捷的⽅式,叫作 Dockerfile,docker build命令⽤于根据给定的Dockerfile内设置的命令构建一个全新的Docker镜像。

docker build参数详解(重点为-t参数)

    --build-arg: 设置构建时的变量。
    --no-cache: 默认为 false。设置该选项,将不使用 Build Cache 构建镜像。
    --pull: 默认为 false。设置该选项,总是尝试 pull 镜像的最新版本。
    --compress: 默认为 false。设置该选项,将使用 gzip 压缩构建的上下文。
    --disable-content-trust: 默认为 true。设置该选项,将对镜像进行验证。
    --file, -f: Dockerfile 的完整路径,默认值为 PATH/Dockerfile。
    --isolation: 默认为 --isolation="default",即 Linux 命名空间;其他选项还有 process 或 hyperv。
    --label: 为生成的镜像设置 metadata。
    --squash: 默认为 false。设置该选项,将新构建出的多个层压缩为一个新层,但是将无法在多个镜像之间共享新层。
    --tag, -t: 镜像的名字及 tag,通常格式为 name:tag 或者 name;可以在一次构建中为一个镜像设置多个 tag。
    --network: 默认为 default。设置该选项,为构建过程中的 RUN 指令设置网络模式。
    --quiet, -q: 默认为 false。设置该选项,压制构建过程的输出,成功后仅打印镜像 ID。
    --force-rm: 默认为 false。设置该选项,总是删除掉中间环节的容器。
    --rm: 默认为 --rm=true,即整个构建过程成功后删除中间环节的容器。

根据Dockerfile构建Docker镜像操作如下

1)创建镜像所在的⽂件夹和Dockerfile⽂件

[root@docker-server ~]# mkdir centos7_mini
[root@docker-server ~]# cd centos7_mini/
[root@docker-server centos7_mini]# touch Dockerfile
[root@docker-server centos7_mini]# vim Dockerfile 
[root@docker-server centos7_mini]# cat Dockerfile 
FROM centos:7
MAINTAINER liumuquan liumuquan@qq.com
RUN touch 1.txt
RUN mkdir /test
[root@docker-server centos7_mini]# vim Dockerfile 
[root@docker-server centos7_mini]# docker build -t liumuquan/centos:777 /root/centos7_mini

。。。。。。。。。。。省略过程。。。。。。。。
这里每执行一步都是一次镜像>容器>镜像的过程


[root@docker-server centos7_mini]# docker images
REPOSITORY         TAG       IMAGE ID       CREATED         SIZE
liumuquan/centos   777       c840aba18439   5 minutes ago   204MB
nginx              latest    605c77e624dd   2 years ago     141MB
tomcat             latest    fb5657adc892   2 years ago     680MB
mysql              5.7       c20987f18b13   2 years ago     448MB
mysql              8.0       3218b38490ce   2 years ago     516MB
registry           latest    b8604a3fe854   2 years ago     26.2MB
ubuntu             latest    ba6acccedd29   2 years ago     72.8MB
centos             7         eeb6ee3f44bd   2 years ago     204MB
[root@docker-server centos7_mini]# 

工作中有一点需要注意,如果是docker官方提供的centos7之前的系统镜像不能直接通过RUN命令使用yum安装,需要更换镜像内的源文件,最好做一个镜像放在阿里云里面

阿里源centos7的镜像dockerfile

[root@docker-server centos7_mini]# cat Dockerfile 
FROM centos:7

RUN rm -rf /etc/yum.repo.d/*
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
RUN yum install -y wget
RUN wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo

如果docker build运行中出错可能会残留一个退出状态的容器或错误的镜像,记得检查删除。

2).创建⼀个jenkins的Dockerfile

[root@docker-server jenkins]# ls
apache-tomcat-9.0.79.tar.gz  jdk-11.0.16_linux-x64_bin.tar.gz  jenkins.war

[root@docker-server jenkins]# vim Dockerfile
[root@docker-server jenkins]# cat Dockerfile
FROM centos:7
MAINTAINER liumuquan liumuquan@qq.com
ENV JAVA_HOME /usr/local/jdk-11.0.16
ENV TOMCAT_HOME /usr/local/apache-tomcat-9.0.79
ENV PATH=$JAVA_HOME/bin:$PATH
ADD apache-tomcat-9.0.79.tar.gz  /usr/local/
ADD jdk-11.0.16_linux-x64_bin.tar.gz /usr/local/
RUN rm -rf /usr/local/apache-tomcat-9.0.79/webapps/*
ADD jenkins.war /usr/local/apache-tomcat-9.0.79/webapps/
RUN rm -rf  jdk-11.0.16_linux-x64_bin.tar.gz apache-tomcat-9.0.79.tar.gz
EXPOSE 8080
ENTRYPOINT ["/usr/local/apache-tomcat-9.0.79/bin/catalina.sh","run"]


[root@docker-server jenkins]# docker build -t jenkins:v1 .

[root@docker-server jenkins]# docker run -itd --name jenkins1 -p 8081:8080 jenkins:v1
1cd044e93dfd69cbe3ebdd0209ca8b5fe9eab37eb4899e3f98402d31bb0ae777

此时使用浏览器访问可以看到jenkins网页

这里有一个问题:CMD与ENTRYPOINT区别

Dockerfile中的CMD

  1. 每个Dockerfile只能包含一个CMD指令。如果存在多个CMD指令,只有最后一个会生效。

  2. CMD指令类似于在运行Docker容器时附加的参数。举例来说:

    • 如果在命令行中运行 docker run -itd --name test image /bin/bash -c,那么相当于在Dockerfile中使用了 CMD ["/bin/bash", "-c"]
    • 如果Dockerfile中已经定义了 CMD ["/bin/bash", "-c"],那么在运行时不需要再额外添加这些参数。如果添加了额外参数,那么默认的CMD参数将被覆盖失效。

Dockerfile中的ENTRYPOINT

  1. 每个Dockerfile只能包含一个ENTRYPOINT指令。如果存在多个ENTRYPOINT指令,只有最后一个会生效。ENTRYPOINT指令可以理解为容器启动时要执行的命令,类似于开机启动。

  2. 举例来说:

    • 如果Dockerfile中定义了 ENTRYPOINT ["tail", "-f", "/var/log/nginx/access.log"],那么在启动容器时将执行这些命令。如果在启动时附加参数,这些参数将被添加到指定的命令后面执行。

Dockerfile优化

  • RUN 命令要尽量写在⼀条⾥,每次 RUN 命令都是在之前的镜像上封装,只会增⼤不会减⼩
  • 每次进⾏依赖安装后,记得yum clean all
  • 选择⽐较⼩的基础镜像。alpine

6、docker镜像仓库(官方)

私有仓库镜像(官方):

registry, 没有图形界⾯。Docker hub官⽅已提供容器镜像registry,⽤于搭建私有仓库

部署方式:

另找一台全新的环境192.168.188.129,按照上方的方式安装docker,修改网络和docker配置

bash 复制代码
[root@localhost ~]# docker pull registry
[root@localhost ~]# docker run -itd -v /home/dockerdata/registry:/var/lib/registry --name "pri_registry" --restart=always -p 5000:5000 registry
28c6f198a14dd02d9665672b3d0545203b52a4fcf9dad6279a760ea942c6712b

    #    下方为命令解释

-v /home/dockerdata/registry:/var/lib/registry: 这个选项 -v 用来将本地文件系统的目录挂载到容器内部的指定路径。具体来说:

    /home/dockerdata/registry 是主机上的目录路径。
    /var/lib/registry 是容器内的路径,通常用于存储 Docker Registry 的数据。
    这样做的效果是将主机上的 /home/dockerdata/registry 目录挂载到容器内的 /var/lib/registry 目录,使得容器内的数据可以持久化到主机上。

--name "pri_registry": 指定容器的名称为 pri_registry。这样可以方便后续通过容器名称来管理和操作容器,而不必依赖于容器ID。


-p 5000:5000: 将容器的端口 5000 映射到主机的端口 5000。这样,外部网络可以通过主机的 5000 端口访问容器内部运行的服务,通常用于提供对应用程序的访问。

检查连通性

bash 复制代码
[root@localhost ~]# curl -I http://127.0.0.1:5000
HTTP/1.1 200 OK
Cache-Control: no-cache
Date: Sun, 04 Aug 2024 09:53:19 GMT

[root@localhost ~]# 

更换128主机进行以下操作,向私有仓库推送镜像

bash 复制代码
[root@docker-server ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
busybox      latest    beae173ccac6   2 years ago    1.24MB

[root@docker-server ~]# docker tag busybox 192.168.188.129:5000/busybox
[root@docker-server ~]# docker images
REPOSITORY                     TAG       IMAGE ID       CREATED        SIZE
busybox                        latest    beae173ccac6   2 years ago    1.24MB
192.168.188.129:5000/busybox   latest    beae173ccac6   2 years ago    1.24MB

    #    此时还无法进行推送,请求默认为https,需要修改配置文件

修改配置文件如下

bash 复制代码
[root@docker-server ~]# vim /etc/docker/daemon.json 
[root@docker-server ~]# cat /etc/docker/daemon.json 
{
  "registry-mirrors": [
          "https://ox288s4f.mirror.aliyuncs.com",
          "https://registry.docker-cn.com",
          "http://hub-mirror.c.163.com",
          "https://mirror.ccs.tencentyun.com"
  ],
  "insecure-registries":["192.168.188.129:5000"]
}
[root@docker-server ~]# systemctl daemon-reload
[root@docker-server ~]# systemctl restart docker

推送刚修改的镜像

bash 复制代码
[root@docker-server ~]# docker push 192.168.188.129:5000/busybox:latest
The push refers to repository [192.168.188.129:5000/busybox]
01fd6df81c8e: Pushed 
latest: digest: sha256:62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee size: 527

查看仓库内容

bash 复制代码
[root@docker-server ~]# curl http://192.168.188.129:5000/v2/_catalog
{"repositories":["busybox"]}

[root@docker-server ~]# curl http://192.168.188.129:5000/v2/busybox/tags/list
{"name":"busybox","tags":["latest"]}

此时我们去查看仓库的宿主机129查看映射出来的目录

bash 复制代码
[root@localhost ~]# ls /home/dockerdata/registry/docker/registry/v2/repositories/busybox/_
_layers/    _manifests/ _uploads/

回到128删除本地的busybox镜像

bash 复制代码
[root@docker-server ~]# docker rmi 192.168.188.129:5000/busybox
[root@docker-server ~]# docker rmi busybox

尝试从私有仓库拉取镜像

bash 复制代码
[root@docker-server ~]# docker pull 192.168.188.129:5000/busybox:latest
latest: Pulling from busybox
5cc84ad355aa: Pull complete 
Digest: sha256:62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee
Status: Downloaded newer image for 192.168.188.129:5000/busybox:latest
192.168.188.129:5000/busybox:latest

7、部署docker web ui应⽤

bash 复制代码
[root@docker-server ~]# docker pull uifd/ui-for-docker
Using default tag: latest
latest: Pulling from uifd/ui-for-docker
841194d080c8: Pull complete 
Digest: sha256:fe371ff5a69549269b24073a5ab1244dd4c0b834cbadf244870572150b1cb749
Status: Downloaded newer image for uifd/ui-for-docker:latest
docker.io/uifd/ui-for-docker:latest

[root@docker-server ~]# docker images
REPOSITORY                     TAG       IMAGE ID       CREATED        SIZE
centos                         7.7       179c4a937f7e   18 hours ago   461MB
192.168.188.129:5000/busybox   latest    beae173ccac6   2 years ago    1.24MB
nginx                          latest    605c77e624dd   2 years ago    141MB
tomcat                         latest    fb5657adc892   2 years ago    680MB
mysql                          5.7       c20987f18b13   2 years ago    448MB
mysql                          8.0       3218b38490ce   2 years ago    516MB
portainer/portainer-ce         latest    0df02179156a   2 years ago    273MB
registry                       latest    b8604a3fe854   2 years ago    26.2MB
ubuntu                         latest    ba6acccedd29   2 years ago    72.8MB
centos                         7         eeb6ee3f44bd   2 years ago    204MB
uifd/ui-for-docker             latest    965940f98fa5   7 years ago    8.1MB

[root@docker-server ~]# docker run -it -d --name docker-web -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock uifd/ui-for-docker
e6d94c2e269d9a98f0b580091a166d894ceccd55ebd17573a120fa4ccc8ad929

使用访问128的9000端口可以进行简单的docker管理

8、harbor仓库

harbor是VMware公司开源的企业级docker registry项目。主要是实现为用户去迅速搭建一个docker registry服务,有可视化界面。

基础环境:

192.168.188.129,防火墙、selinux已关闭,yum源更改为国内源,docker已部署。

所需安装包需要外部网络环境,这里使用以前下载保存在云盘的安装包

bash 复制代码
链接:https://pan.baidu.com/s/1619AcrAXmhaTKKXS5ahXNQ?pwd=1ee5 
提取码:1ee5 

8.1、harbor部署

bash 复制代码
[root@localhost ~]# ls
anaconda-ks.cfg  docker-compose-linux-2.2.3-x86_64  harbor-offline-installer-v1.10.10.tgz
[root@localhost ~]# mv docker-compose-linux-2.2.3-x86_64 /usr/local/bin/docker-compose
[root@localhost ~]# chmod +x /usr/local/bin/docker-compose
[root@localhost ~]# tar xf harbor-offline-installer-v1.10.10.tgz 
[root@localhost ~]# ls
anaconda-ks.cfg  harbor  harbor-offline-installer-v1.10.10.tgz

这个harbo内部其实是启动脚本和多个组件的镜像文件,需要先修改harbor配置文件

bash 复制代码
[root@localhost ~]# ls
anaconda-ks.cfg  harbor  harbor-offline-installer-v1.10.10.tgz
[root@localhost ~]# cd harbor
[root@localhost harbor]# ls
common.sh  harbor.v1.10.10.tar.gz  harbor.yml  install.sh  LICENSE  prepare
[root@localhost harbor]# vim harbor.yml

修改内容如下

bash 复制代码
    #    修改ip为本机ip

hostname: 192.168.188.129

    #    将https部分内容全部注释

# https related config
#https:
  # https port for harbor, default is 443
  #port: 443
  # The path of cert and key files for nginx
  #certificate: /your/certificate/path
  #private_key: /your/private/key/path

执行安装脚本

bash 复制代码
[root@localhost harbor]# ./install.sh 

访问harbor的web页面http://192.168.188.129:80(注意此处,我注释掉了https,直接输入ip谷歌火狐会默认补上https)

正常进入harbor页面

在129配置harbor的https访问

bash 复制代码
[root@localhost ~]# mkdir -p /data/cert/
[root@localhost ~]# openssl genrsa -out /data/cert/server.key 2048
Generating RSA private key, 2048 bit long modulus
..+++
.........................+++
e is 65537 (0x10001)

[root@localhost ~]# openssl req -x509 -new -nodes -key /data/cert/server.key -subj "/CN=192.168.188.129" -days 3650 -out /data/cert/server.crt

[root@localhost ~]# ls /data/cert/
server.crt  server.key

[root@localhost ~]# cd /root/harbor
[root@localhost harbor]# ls
common     docker-compose.yml      harbor.yml  LICENSE
common.sh  harbor.v1.10.10.tar.gz  install.sh  prepare
[root@localhost harbor]# vim harbor.yml 

将上面注释掉的https部分修改如下

bash 复制代码
# https related config
https:
  # https port for harbor, default is 443
  port: 443
  # The path of cert and key files for nginx
  certificate: /data/cert/server.crt
  private_key: /data/cert/server.key

重启harbor加载配置

bash 复制代码
[root@localhost harbor]# ./prepare


    #    以下扩展内容
如果上面方式重启失效,或者执行后https访问仍然失败,可以在harbor目录下使用如下命令重装容器
[root@localhost harbor]# docker-compose down
[root@localhost harbor]# docker-compose up -d

8.2、harbor基础使用

演示时以128主机为客户端,配置如下,此处注意主机名分辨操作对象

bash 复制代码
[root@docker-server ~]# vim /etc/docker/daemon.json 
[root@docker-server ~]# cat /etc/docker/daemon.json 
{
  "registry-mirrors": [
          "https://ox288s4f.mirror.aliyuncs.com",
          "https://registry.docker-cn.com",
          "http://hub-mirror.c.163.com",
          "https://mirror.ccs.tencentyun.com"
  ],
  "insecure-registries":["192.168.188.129"]
}
[root@docker-server ~]# systemctl daemon-reload
[root@docker-server ~]# systemctl restart docker

创建项目(这里创建一个私有的,私有的项目更麻烦可以演示的效果更多)

进入刚创建的项目

创建用户

将新创建的用户添加到centos项目中,并赋予项目管理员权限

使用 128主机向harbor内推送镜像

bash 复制代码
[root@docker-server ~]# docker images
REPOSITORY                     TAG       IMAGE ID       CREATED        SIZE
registry                       latest    b8604a3fe854   2 years ago    26.2MB

[root@docker-server ~]# docker tag registry:latest 192.168.188.129/centos/registry:v1996

[root@docker-server ~]# docker images
REPOSITORY                        TAG       IMAGE ID       CREATED        SIZE
registry                          latest    b8604a3fe854   2 years ago    26.2MB
192.168.188.129/centos/registry   v1996     b8604a3fe854   2 years ago    26.2MB

    #    因为是非公开(私有)项目,推送前需要先登录

[root@docker-server ~]# docker login -u liumuquan -p Liumuquan@123 192.168.188.129
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

[root@docker-server ~]# docker push 192.168.188.129/centos/registry:v1996
The push refers to repository [192.168.188.129/centos/registry]
aeccf26589a7: Pushed 
f640be0d5aad: Pushed 
aa4330046b37: Pushed 
ad10b481abe7: Pushed 
69715584ec78: Pushed 
v1996: digest: sha256:36cb5b157911061fb610d8884dc09e0b0300a767a350563cbfd88b4b85324ce4 size: 1363
[root@docker-server ~]# 
    #    推送成功

推送完成后返回web页面查看

推送另一个版本

bash 复制代码
[root@docker-server ~]# docker tag registry:latest 192.168.188.129/centos/registry:v2024
[root@docker-server ~]# docker push 192.168.188.129/centos/registry:v2024
The push refers to repository [192.168.188.129/centos/registry]
aeccf26589a7: Layer already exists 
f640be0d5aad: Layer already exists 
aa4330046b37: Layer already exists 
ad10b481abe7: Layer already exists 
69715584ec78: Layer already exists 
v2024: digest: sha256:36cb5b157911061fb610d8884dc09e0b0300a767a350563cbfd88b4b85324ce4 size: 1363
[root@docker-server ~]# 

在客户端拉取镜像命令获取方式(非公开项目需要提前登录)

一个harbor可以有多个项目,一个项目可以有多个仓库,一个仓库可以存放多个镜像

注:公有仓库和私有仓库区别为:

  • 私有仓库拉取/推送均需要登陆
  • 公有仓库推送需要登陆, 拉取无需登录。

9、Docker资源限制

在使用 Docker 运行容器时,一台主机上可能会同时运行数百个容器。这些容器虽然互相隔离,但它们共享相同的CPU、内存和磁盘资源。如果不对容器使用的资源进行限制,容器之间会相互影响。具体来说,小范围的影响会导致容器资源使用不公平;而大范围的影响可能会耗尽主机和集群的资源,导致服务完全不可用。

CPU 和内存的资源限制已经相对成熟且易于使用,能够满足大部分用户的需求。尽管目前无法动态限制磁盘容量,但限制磁盘读写速度已经能够适应许多场景。

资源限制不仅使得我们能够为容器设置合理的 CPU、内存等资源以便更好地管理,同时也能有效地预防恶意攻击和异常,对容器而言是非常重要的功能。

这里需要引入一个系统压力测试工具stress,可以使用yum安装,这里我们使用一个镜像生成一个stress

9.1、cpu资源限制

什么是cpu share:Docker允许用户为每个容器设置一个 CPU share 数字,默认情况下每个容器的 share 是 1024。这个 share 是相对的,没有具体的绝对意义。在主机上同时运行多个容器时,每个容器占用的 CPU 时间比例取决于其 share 在总额中的比例。Docker会根据主机上运行的容器和进程的动态情况,调整每个容器使用 CPU 时间的比例。简单来说share最大值为1024,share与权重类似,数字越大优先级权重越高。

可以参考下表理解

|----------|----------|----------|----------|
| A容器share | B容器share | A容器所占cpu | B容器所占cpu |
| 1024 | 1024 | 50% | 50% |
| 1024 | 512 | 约等于70% | 约等于30% |
| 该容器被删除 | 512 | / | 100% |

好处:能保证 CPU 尽可能处于运⾏状态,充分利⽤ CPU 资源,⽽且保证所有容器的相对公平;缺点:⽆法指定容器使⽤ CPU 的确定值。

实际操作如下:

bash 复制代码
[root@docker-server ~]# docker run -d --cpus 1.5 progrium/stress --cpu 3



--cpus 1.5: 这个参数用来限制容器可以使用的 CPU 资源。在这里,指定容器最多可以使用主机 1.5 个 CPU 的资源。通常情况下,这个值应该不超过主机的物理 CPU 核心数,但 Docker 允许超额分配,因此可以指定小数值来实现精确分配。

    如果主机有多个 CPU 核心,1 个 CPU 表示一个核心的全部时间。
    1.5 表示容器可以使用一个核心加上该核心50%的时间。这种设置在超线程或虚拟化环境中特别有用。


--cpu 3: 这是传递给 progrium/stress 的参数之一。它指示在容器中运行 3 个进程,每个进程不断计算随机数的平方,以模拟 CPU 负载。这将导致容器占用大量的 CPU 资源,具体占用多少取决于主机上可用的物理 CPU 核心数和 --cpus 参数的设置。


总的来说这条命令是:启动三个进程占用cpu,但是占用的总量是150%,也就是平分到每个cpu50%

如果设置的 --cpus 值⼤于主机的 CPU 核数,docker 会直接报错

如果多个容器都设置了 --cpus ,并且它们之和超过主机的 CPU 核数,并不会导致容器失败或者退出, 这些容器之间会竞争使⽤ CPU,具体分配的 CPU 数量取决于主机运⾏情况和容器的 CPU share 值。也就是说 --cpus 只能保证在 CPU 资源充⾜的情况下容器最多能使⽤的 CPU 数。想要任何条件下都保证cpu的完美使用是不可能的。

cpu绑定操作

bash 复制代码
[root@docker-server ~]# docker run --rm -it --cpuset-cpus=0,1 progrium/stress --cpu 2

可以通过 --cpuset 参数让容器只运⾏在前两个核上

只是官方手册有这种配置方式,工作生产环境中不会这样使用

9.2、mem资源限制

Docker 默认不限制容器内存使用,容器可以使用主机提供的所有内存。这带来了安全风险,因为恶意软件或内存泄漏可能导致主机内存耗尽,使服务不可用。为了避免这种情况,可以为每个容器设置内存使用上限,超过上限时容器会被kill,而不是继续消耗主机资源。

然而,限制内存使用也会带来新的问题。设置过小的内存限制可能导致服务被提前终止,而过大则会浪费资源。

最佳做法包括:

  1. 在测试阶段对应用进行内存压力测试,理解其正常工作负载下的内存需求。
  2. 必须为容器设置合理的内存上限,确保主机资源充足。
  3. 尽量避免使用 swap,因为其使用会增加内存管理的复杂性,并不利于资源调度,国内主流云厂商默认不使用swap。

docker 限制容器内存使⽤量:

docker 启动参数中,和内存限制有关的包括(参数的值⼀般是内存⼤⼩,也就是⼀个正数,后⾯跟着 内存单位 b、k、m、g,分别对应 bytes、KB、MB、和 GB):

-m --memory:容器能使⽤的最⼤内存⼤⼩,最⼩值为 4m

如果限制容器的内存使⽤为 64M,在申请 64M 资源的情况下,容器运⾏正常:

bash 复制代码
[root@docker-server ~]# docker run --rm -it -m 64m progrium/stress --vm 1 --vm-bytes 64M --vm-hang 0

-m 64m: 这个选项限制容器可以使用的内存量。在这里,64m 表示最大内存为 64 MB。如果容器尝试使用超过这个限制的内存,Docker 将会杀死该容器。这是为了防止容器耗尽主机的内存资源。



--vm 1 --vm-bytes 64M --vm-hang 0: 这些是传递给 progrium/stress 工具的参数:

    --vm 1: 启动一个虚拟内存工作集(Virtual Memory working set)。
    --vm-bytes 64M: 指定每个工作集的大小为 64 MB。
    --vm-hang 0: 表示不让虚拟内存操作挂起。

9.3、io 资源限制

⽬前 docker ⽀持对磁盘的读写速度进⾏限制,但是并没有⽅法能限制容器能使⽤的磁盘容量(⼀旦磁盘 mount 到容器⾥,容器就能够使⽤磁盘的所有容量),这个在工作中完全没有用到过

bash 复制代码
docker run --rm -it --device-read-bps=/dev/sda:1mb --device-write-bps=/dev/sda:1mb ubuntu

--device-read-bps=/dev/sda:1mb 和 --device-write-bps=/dev/sda:1mb:
限制容器对 /dev/sda 设备的读写速率为每秒 1 MB。这有助于控制容器的磁盘 IO,以防止其对系统其他部分的影响过大。

这一项和cpu时间资源配额(限制了容器每秒可以使用的 CPU 时间),高级网络管理任务授权类似,都是极少在工作生产中使用的。

10、Centos7容器(systemd整合)

因为 systemd 要求 CAPSYSADMIN 权限,从⽽得到了读取到宿主机 cgroup 的能⼒,CentOS7 中已经⽤ fakesystemd 代替了 systemd 。 但是为了方便使⽤systemd,可⽤参考下⾯的 Dockerfile:

dockerfile内容如下

这个7.7是按照上文方法更换过源文件的镜像

bash 复制代码
[root@docker-server systemd]# cat Dockerfile 
FROM centos:7.7
MAINTAINER "liumuquan" liumuquan@qq.com
ENV container docker

RUN yum -y swap -- remove fakesystemd -- install systemd systemd-libs
RUN yum -y update; yum clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;

VOLUME [ "/sys/fs/cgroup" ]

CMD ["/usr/sbin/init"]


[root@docker-server systemd]# 

启动容器的参数也要有所不同

为了运⾏⼀个包含 systemd 的容器,需要使⽤--privileged选项, 并且挂载主机的 cgroups ⽂件夹。

bash 复制代码
[root@docker-server systemd]# docker run --privileged -tid -v /sys/fs/cgroup:/sys/fs/cgroup:ro local/c7.7-systemd
d13e20b6019a9b90fb8fece87dea5bc0cdd6d9ff03ff5a7b31747239c9f32f9c
[root@docker-server systemd]# docker ps
CONTAINER ID   IMAGE                COMMAND            CREATED          STATUS          PORTS     NAMES
d13e20b6019a   local/c7.7-systemd   "/usr/sbin/init"   25 seconds ago   Up 24 seconds             fervent_faraday
[root@docker-server systemd]# docker exec --privileged -it fervent_faraday /bin/bash
[root@d13e20b6019a /]# systemctl get-default
multi-user.target

11、Docker数据存储位置

查看和修改Docker数据存储位置方式如下

bash 复制代码
[root@docker-server ~]# docker info | grep Root
 Docker Root Dir: /var/lib/docker
[root@docker-server ~]# mkdir data
[root@docker-server ~]# vim /usr/lib/systemd/system/docker.service

    #    修改如下
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --data-root=/data

原文:ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
修改方式为在原文后面加上--data-root=新的镜像路径

[root@docker-server ~]# systemctl daemon-reload
[root@docker-server ~]# systemctl restart docker
[root@docker-server ~]# docker info | grep Root
 Docker Root Dir: /data

12、Docker⽹络管理

这里开始下面的内容实际工作上很少用到,这部分工作被k8s替代

查看当前网络类型

bash 复制代码
[root@docker-server ~]# docker network list
NETWORK ID     NAME      DRIVER    SCOPE
5480147dd1f8   bridge    bridge    local
5549e6235f77   host      host      local
3251dab47b08   none      null      local

12.1、bridge:⽹络桥接

bash 复制代码
默认情况下启动、创建容器都是⽤该模式,所以每次docker容器重启时会按照顺序获取对应ip地址。
与vm的nat模式十分相似

12.2、none:⽆指定⽹络

bash 复制代码
启动容器时,可以通过--network=none,docker容器不会分配局域⽹ip
此模式下容器不获取ip

12.3、host:主机⽹络

bash 复制代码
docker容器和主机共⽤⼀个ip地址。
使⽤host⽹络创建容器:
[root@docker-server ~]# docker run -it --name nginx1 --net host nginx

此时访问宿主机端口可直接看到容器内运行的nginx首页

12.4、⾃定义⽹络类型

bash 复制代码
[root@docker-server ~]# docker network create --subnet=192.168.0.0/16 staticnet

[root@docker-server ~]# docker network list
NETWORK ID     NAME        DRIVER    SCOPE
5480147dd1f8   bridge      bridge    local
5549e6235f77   host        host      local
3251dab47b08   none        null      local
a65eb8c26796   staticnet   bridge    local


    #    使⽤新的⽹络类型创建并启动容器
[root@docker-server ~]# docker run -itd --name server --net staticnet --ip 192.168.0.2 daocloud.io/library/centos:7.7


    #    删除已创建⽹络
[root@docker-server]# docker network rm staticnet

12.5、异主容器互联

拓扑图如下

实现容器互联一般有两个方式:

  • 路由⽅式
  • 配置open vswitch虚拟交换机

这里作为理解即可

相关推荐
寒笙LED9 分钟前
C++详细笔记(六)string库
开发语言·c++·笔记
嚯——哈哈14 分钟前
从入门到精通:解析如何使用亚马逊云服务器(AWS EC2)
运维·服务器·aws
岳不谢41 分钟前
VPN技术-VPN简介学习笔记
网络·笔记·学习·华为
编程修仙1 小时前
Collections工具类
linux·windows·python
芝麻团坚果1 小时前
对subprocess启动的子进程使用VSCode python debugger
linux·ide·python·subprocess·vscode debugger
Elastic 中国社区官方博客1 小时前
Elasticsearch 中的热点以及如何使用 AutoOps 解决它们
大数据·运维·elasticsearch·搜索引擎·全文检索
写点什么啦1 小时前
[debug]不同的window连接ubuntu的vscode后无法正常加载kernel
linux·vscode·ubuntu·debug
wellnw1 小时前
[ubuntu]编译共享内存读取出现read.c:(.text+0x1a): undefined reference to `shm_open‘问题解决方案
linux·ubuntu
不爱学习的YY酱1 小时前
【操作系统不挂科】<CPU调度(13)>选择题(带答案与解析)
java·linux·前端·算法·操作系统
DC_BLOG1 小时前
Linux-Nginx虚拟主机
linux·运维·nginx