容器技术 - docker

文章目录
  • 一、Docker简介
    • [1.1 Docker诞生](#1.1 Docker诞生)
    • [1.2 Docker相关解释](#1.2 Docker相关解释)
    • [1.3 Docker与传统虚拟化对比](#1.3 Docker与传统虚拟化对比)
    • [1.4 Docker的构成](#1.4 Docker的构成)
  • 二、Docker安装
    • [2.1 Docker的安装方式](#2.1 Docker的安装方式)
    • [2.2 Docker镜像加速配置](#2.2 Docker镜像加速配置)
    • [2.3 Docker化应用体验](#2.3 Docker化应用体验)
  • 三、Docker容器管理
    • [3.1 Docker基础概念](#3.1 Docker基础概念)
    • [3.2 Docker基础命令](#3.2 Docker基础命令)
    • [3.3 单一容器管理命令](#3.3 单一容器管理命令)
    • [3.4 Run延伸](#3.4 Run延伸)
    • [3.5 Docker-Compose](#3.5 Docker-Compose)
  • 四、Docker镜像管理
    • [4.1 镜像的特性](#4.1 镜像的特性)
    • [4.2 容器转换为镜像](#4.2 容器转换为镜像)
    • [4.3 Dockerfile](#4.3 Dockerfile)
    • [4.4 镜像的导出以及导入](#4.4 镜像的导出以及导入)
  • 五、镜像仓库构建
    • [5.1 官方仓库构建方式](#5.1 官方仓库构建方式)
    • [5.2 Harbor构建](#5.2 Harbor构建)
  • 六、Docker中的网络
    • [6.1 Linux 内核中的 NameSpace](#6.1 Linux 内核中的 NameSpace)
    • [6.2 Docker网络通讯示意图](#6.2 Docker网络通讯示意图)
    • [6.3 Docker中的防火墙规则](#6.3 Docker中的防火墙规则)
    • [6.4 Docker网络的修改](#6.4 Docker网络的修改)
    • [6.5 端口的暴露方式](#6.5 端口的暴露方式)
    • [6.6 网络隔离](#6.6 网络隔离)
  • 七、数据存储
    • [7.1 数据卷特性](#7.1 数据卷特性)
    • [7.2 数据卷的意义](#7.2 数据卷的意义)
    • [7.3 数据卷的类型](#7.3 数据卷的类型)
    • [7.4 容器中使用数据卷的方法](#7.4 容器中使用数据卷的方法)
    • [7.5 存储驱动](#7.5 存储驱动)
  • 八、资源限制
    • [8.1 内存资源限制](#8.1 内存资源限制)
    • [8.2 内存限制设置方式](#8.2 内存限制设置方式)
    • [8.3 参数示意图](#8.3 参数示意图)
    • [8.4 CPU资源限制](#8.4 CPU资源限制)
    • [8.5 限制性实验](#8.5 限制性实验)

一、Docker简介

所需软件

链接:http:// https://pan.baidu.com/s/5XplIFUDTP1K51LxEaPt3VQ

复制这段内容后打开百度网盘手机App,操作更方便哦

1.1 Docker诞生

Docker是dotcloud公司开源的一款产品dotcloud是2010年新成立的一家公司,主要基于PAAS(PlatfromasaService)平台为开发者提供服务。2013年10月dotcloud公司改名为Docker股份有限公司

1.2 Docker相关解释

  • LinuxContainer是一种内核虚拟化技术可以提供轻量级的虚拟化,以便隔离进程和资源
  • Docker是PAAS提供商dotCloud开源的一个基于LXC( LinuxContainer**)的高级容器引擎** ,源代码托管在Github上,基于go语言并遵从Apache2.0协议开源
  • Docker设想是交付运行环境如同海运,OS如同一个货轮,每一个在OS基础上的软件都如同一个集装箱,用户可以通过标准化手段自由组装运行环境,同时集装箱的内容可以由用户自定义,也可以由专业人员制造

1.3 Docker与传统虚拟化对比


比较 Docker 和传统虚拟化方式的不同之处:

  • 传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程。
  • 而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
  • 每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。

1.4 Docker的构成

  • Docker仓库:https://hub.docker.com
  • Docker自身组件
    • DockerClient:Docker的客户端
    • DockerServer:Dockerdaemon的主要组成部分,接受用户通过DockerClient发出的请求,并按照相应的路由规则实现路由分发
    • Docker镜像:Docker镜像运行之后变成容器(dockerrun)

二、Docker安装

2.1 Docker的安装方式

Script Install(脚本安装)

方式一:

bash 复制代码
[root@localhost ~]$ yum update
[root@localhost ~]$ curl -sSL https://get.docker.com/ | sh
[root@localhost ~]$ systemctl start docker
[root@localhost ~]$ systemctl enable docker
[root@localhost ~]$ docker run hello-world

方式二:(一键安装)

bash 复制代码
bash <(wget -qO- https://xuanyuan.cloud/docker.sh)

YUM Install

Ubuntu

bash 复制代码
Ubuntu(使用 apt-get 进行安装)

# step 1: 安装必要的一些系统工具
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg

# step 2: 信任 Docker 的 GPG 公钥
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Step 3: 写入软件源信息
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
 
# Step 4: 安装Docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# apt-cache madison docker-ce
#   docker-ce | 17.03.1~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
#   docker-ce | 17.03.0~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
# Step 2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.1~ce-0~ubuntu-xenial)
# sudo apt-get -y install docker-ce=[VERSION]

centos

bash 复制代码
# step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils

# Step 2: 添加软件源信息
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# Step 3: 安装Docker
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Step 4: 开启Docker服务
sudo service docker start

# 注意:
# 官方软件源默认启用了最新的软件,您可以通过编辑软件源的方式获取各个版本的软件包。例如官方并没有将测试版本的软件源置为可用,您可以通过以下方式开启。同理可以开启各种测试版本等。
# vim /etc/yum.repos.d/docker-ce.repo
#   将[docker-ce-test]下方的enabled=0修改为enabled=1
#
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# yum list docker-ce.x86_64 --showduplicates | sort -r
#   Loading mirror speeds from cached hostfile
#   Loaded plugins: branch, fastestmirror, langpacks
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            docker-ce-stable
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            @docker-ce-stable
#   docker-ce.x86_64            17.03.0.ce-1.el7.centos            docker-ce-stable
#   Available Packages
# Step2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.0.ce.1-1.el7.centos)
# sudo yum -y install docker-ce-[VERSION]
bash 复制代码
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://1ms.run/"
  ]
}
EOF
systemctl daemon-reload && systemctl restart docker


#或一键配置
# 一键配置,简单快捷,告别拉取超时
sudo bash -c "$(curl -sSL https://n3.ink/helper)"


https://1ms.run(1毫米镜像源)

会有一个安装包docker-compose-plugin-2.27.1-1.el7.x86_64.rpm 阿里云yum源里没有

手动安装

软件:http:// https://pan.baidu.com/s/5XplIFUDTP1K51LxEaPt3VQ

RPM Install

https://download.docker.com/linux/centos/7/x86_64/stable/Packages/

软件包:http:// https://pan.baidu.com/s/5XplIFUDTP1K51LxEaPt3VQ

bash 复制代码
#环境设置
[root@localhost ~]$ yum -y install iptables-services
[root@localhost ~]$ systemctl start iptables && systemctl enable iptables
[root@localhost ~]$ iptables -F && service iptables save



[root@localhost ~]$ mkdir docker && mv docker* docker/ && cd docker

#安装docker
[root@localhost ~]$ yum -y install * 

#启动docker
[root@localhost ~]$ systemctl start docker && systemctl enable docker

#测试命令
[root@localhost ~]$ docker run hello-world

2.2 Docker镜像加速配置

阿里云Docker加速官网:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

bash 复制代码
[root@localhost ~]$ cp /lib/systemd/system/docker.service /etc/systemd/system/docker.service
[root@localhost ~]$ chmod 777 /etc/systemd/system/docker.service
[root@localhost ~]$ vim /etc/systemd/system/docker.service
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd --registry-mirror=https://kfp63jaj.mirror.aliyuncs.com




[root@localhost ~]$ systemctl daemon-reload
[root@localhost ~]$ systemctl restart docker
[root@localhost ~]$ ps -ef | grep docker

非阿里云的产品加速镜像并不适用

推荐:

1、Docker镜像极速下载服务 - 毫秒镜像

2、Docker 镜像免费公共测试访问入口 | 轩辕镜像免费版

2.3 Docker化应用体验

环境分析

WordPress运行环境需要如下软件的支持:

  • PHP5.6或更新软件
  • MySQL5.6或更新版本
  • Apache和mod_rewrite模块
bash 复制代码
#下载镜像
[root@localhost ~]$ docker pull mariadb
[root@localhost ~]$ docker pull wordpress


[root@localhost ~]$ docker run --name db --env MYSQL_ROOT_PASSWORD=example -d mariadb
#docker run 把镜像转换成一个容器
#--name db 给这个镜像起一个名字db
#--env MYSQL_ROOT_PASSWORD=example 指定环境变量
#-d 后台运行容器,并返回容器ID
#mariadb 镜像名字
#docker run是利用镜像生成容器,并启动容器,而docker start是启动一个之前生成过的容器


[root@localhost ~]$ docker run --name MyWordPress --link db:mysql -p 8080:80 -d wordpress
#--link 衔接关系
#-p 端口映射,主机(宿主)端口:容器端口

三、Docker容器管理

3.1 Docker基础概念

Docker的三个重要概念:

  • 镜像(image)

    镜像,简单的来说,就是面向对象中的类,相当于一个模板。Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。

  • 容器(container)
    Docker 利用容器(Container)独立运行的一个或一组应用。容器是用镜像创建的运行实例。可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

  • 仓库(repository)

    仓库(Repository)是集中存放镜像文件的场所。

Docker指令的基本用法:

bash 复制代码
docker + 命令关键字(COMMAND) + 一系列的参数

3.2 Docker基础命令

命令 含义
docker info 守护进程的系统资源设置
docker search 镜像名 Docker仓库的查询
docker pull 镜像名 Docker仓库的下载
docker images Docker镜像的查询
docker rmi 镜像id(或镜像名:版本号) Docker镜像的删除
docker ps 容器的查询
docker run 容器的创建启动
docker rm 容器id号(或者 容器名称) 容器的删除
docker start/stop 容器启动停止

Docker指令除了单条使用外,还支持赋值、解析变量、嵌套使用

3.3 单一容器管理命令

每个容器被创建后,都会分配一个CONTAINER ID作为容器的唯一标示,后续对容器的启动、停止、修改、删除等所有操作,都是通过CONTAINER ID或者容器名来完成,偏向于数据库概念中的主键

命令 含义
docker ps --no-trunc 查看
docker stop/start CONTAINERID 停止
docker start/stop MywordPress 通过容器别名启动/停止
docker inspect MywordPress 查看容器所有基本信息
docker logs MywordPress 查看容器日志
docker stats MywordPress 查看容器所占用的系统资源
docker exec 容器名 容器内执行的命令 容器执行命令
docker exec -it 容器名 /bin/bash 登入容器的bash

3.4 Run延伸

参数 含义
--restart=always 容器的自动启动
-h x.xx.xx 设置容器主机名
- dns xx.xx.xx.xx 设置容器使用的DNS服务器
--dns-search DNS搜索设置
--add-host hostname:IP 注入hostname<>IP解析
--rm 服务停止时自动删除

3.5 Docker-Compose

Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

安装Docker-compose

bash 复制代码
[root@localhost ~]$curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

[root@localhost ~]$ chmod +x /usr/local/bin/docker-compose
[root@localhost ~]$ docker-compose --version

Docker-compose用法

参数 含义
-f 指定使用的yaml文件位置
ps 显示所有容器信息
restart 重新启动容器
logs 查看日志信息
config -q 验证yaml配置文件是否正确
stop 停止容器
start 启动容器
up -d 启动容器项目
pause 暂停容器
unpause 恢复暂停
rm 删除容器

示例

bash 复制代码
[root@localhost ~]$ vim wordpress.yaml
version: '2' #版本

services:   #定义一种服务
  db: #第一个容器的名字
    image: mysql:5.7
    restart: always
    environment: #环境变量
      MYSQL_ROOT_PASSWORD: somewordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress

  wordpress: #第二个容器的名字
    depends_on:    #相当于--link
      - db
    image: wordpress:latest
    restart: always
    ports:
      - "8000:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress



[root@localhost ~]$ mv wordpress.yaml docker-compose.yaml
[root@localhost ~]$ docker-compose up -d #启动

[root@localhost ~]$ docker ps -a  #启动成功
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                   PORTS                  NAMES
cceb5a8ed799        wordpress:latest    "docker-entrypoint..."   9 minutes ago       Up 9 minutes             0.0.0.0:8000->80/tcp   root_wordpress_1_a2264aaee26c
d3f99d415eac        mysql:5.7           "docker-entrypoint..."   9 minutes ago       Up 9 minutes             3306/tcp, 33060/tcp    root_db_1_87a386700a32
02428d68a259        wordpress           "docker-entrypoint..."   3 weeks ago         Exited (0) 3 weeks ago                          MyWordPress
ae0f8de9e8fd        mariadb             "docker-entrypoint..."   3 weeks ago         Exited (0) 3 weeks ago                          db
8ac302f04535        hello-world         "/hello"                 3 weeks ago         Exited (0) 3 weeks ago                          kickass_noyce



[root@localhost ~]$ docker-compose logs  #启动成功

命令总结:

四、Docker镜像管理

4.1 镜像的特性

容器创建时需要指定镜像,每个镜像都由唯一的标示ImageID,和容器的ContainerID一样,默

认128位,可以使用前16为缩略形式,也可以使用镜像名与版本号两部分组合唯一标示,如果省

略版本号,默认使用最新版本标签(latesr)

镜像的分层: Docker的镜像通过联合文件系统(union filesystem)将各层文件系统叠加在一起

bootfs:用于系统引导的文件系统,包括bootloader和kernel,容器启动完成后会被卸载以节省

内存资源

roofs:位于bootfs之上,表现为Docker容器的跟文件系统

传统模式中,系统启动时,内核挂载rootfs时会首先将其挂载为"只读"模式,完整性自检

完成后将其挂载为读写模式
Docker中,rootfs由内核挂载为"只读"模式,而后通过UFS技术挂载一个"可写"层

1.已有分层只能读不能修改

2.上层镜像优先级大于底层镜像

4.2 容器转换为镜像

bash 复制代码
[root@localhost ~]$ docker commit CID xx.xx.xx
bash 复制代码
#指定仓库拉取镜像
[root@localhost ~]$ docker pull hub.c.163.com/public/centos:6.7-tools

#启动mysql容器
[root@localhost ~]$ docker run --name mysql -d hub.c.163.com/public/centos:6.7-tools

#进入容器
[root@localhost ~]$ docker exec -it mysql /bin/bash

#在容器内安装mysql
[root@396607d4389d /]$ yum -y install mysql mysql-server


[root@localhost ~]$ docker commit mysql mysql:5.1

4.3 Dockerfile

Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令。Docker程序将这些Dockerfile指令翻译真正的Linux命令。Dockerfile有自己书写格式和支持的命令,Docker程序解决这些命令间的依赖关系,类似于Makefile。Docker程序将读取Dockerfile,根据指令生成定制的image

转换命令

bash 复制代码
[root@localhost ~]$ docker build -t wangyang/jdk-tomcat .

Dockerfile语法

1、FROM(指定基础image):

构建指令,必须指定且需要在Dockerfile其他指令的前面。后续的指令都依赖于该指令指定的image。

FROM指令指定的基础image可以是官方远程仓库中的,也可以位于本地仓库

bash 复制代码
FROM centos:7.2 #有且只有一个
FROM centos

2、MAINTAINER(用来指定镜像创建者信息):

构建指令,用于将image的制作者相关的信息写入到image中。当我们对该image执行docker inspect命令时,输出中有相应的字段记录该信息。

bash 复制代码
MAINTAINER wangyang"wangyang@itxdl.cn"
#maintainer

3、RUN(安装软件用):

构建指令,RUN可以运行任何被基础image支持的命令。如基础image选择了Centos,那么软件管理部分只能使用Centos的包管理命令,需要执行shell命令,前面加run

bash 复制代码
#常用
RUN cd /tmp && curl-L http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.8/bin/apache-tomcat-7.0.8.tar.gz'|tar-xz  

RUN ["/bin/bash","-c","echo hello"]

4、CMD(设置container容器 启动时执行的操作):

设置指令,用于container启动时指定的操作。该操作可以是执行自定义脚本,也可以是执行系统命令。该指令只能在文件中存在一次,如果有多个,则只执行最后一条

bash 复制代码
CMD echo "Hello World!"

5、ENTRYPOINT(设置container启动时执行的操作):

设置指令,指定容器启动时执行的命令,可以多次设置,但是只有最后一个有效。

bash 复制代码
ENTRYPOINT ls -l
#entrypoint ls -l

该指令的使用分为两种情况,一种是独自使用,另一种和CMD指令配合使用。当独自使用时,如果你还使用了CMD命令且CMD是一个完整的可执行的命令,那么CMD指令和ENTRYPOINT会互相覆盖只有最后一个CMD或者ENTRYPOINT有效

bash 复制代码
#CMD指令将不会被执行,只有ENTRYPOINT指令被执行
CMD echo "Hello World!"
ENTRYPOINT ls -l
#entrypoint

另一种用法和CMD指令配合使用来指定ENTRYPOINT的默认参数,这时CMD指令不是一个完整的可执行命令,仅仅是参数部分;ENTRYPOINT指令只能使用JSON方式指定执行命令,而不能指定参数

bash 复制代码
FROM ubuntu
CMD ["-l"]
ENTRYPOINT ["/usr/bin/ls"]
#entrypoint

6、USER(设置container容器的用户):

设置指令,设置启动容器的用户,默认是root用户

bash 复制代码
USER daemon = ENTRYPOINT ["memcached","-u","daemon"]
#entrypoint

7、EXPOSE(指定容器需要映射到宿主机器的端口):

设置指令,该指令会将容器中的端口映射成宿主机器中的某个端口。当你需要访问容器的时候,可以不是用容器的IP地址而是使用宿主机器的IP地址和映射后的端口。要完成整个操作需要两个步骤,首先在Dockerfile使用EXPOSE设置需要映射的容器端口,然后在运行容器的时候指定-p选项加上EXPOSE设置的端口,这样EXPOSE设置的端口号会被随机映射成宿主机器中的一个端口号。也可以指定需要映射到宿主机器的那个端口,这时要确保宿主机器上的端口号没有被使用。EXPOSE指令可以一次设置多个端口号,相应的运行容器的时候,可以配套的多次使用 -p 选项。

bash 复制代码
#映射一个端口
EXPOSE 22

#相应的运行容器使用的命令
docker run -p port1 image

#映射多个端口
EXPOSE port1 port2 port3

#相应的运行容器使用的命令
docker run -p port1 -p port2 -p port3 image

#还可以指定需要映射到宿主机器上的某个端口号
docker run -p host_port1:port1-p host_port2:port2 -p host_port3:port3 image

8、ENV(用于设置环境变量):构建指令,在image中设置一个环境变量

设置了后,后续的RUN命令都可以使用,container启动后,可以通过docker inspect查看这个环

境变量,也可以通过在docker run --env key=value时设置或修改环境变量。假如你安装了JAVA程序,需要设置JAVA HOME,那么可以在Dockerfile中这样写:

bash 复制代码
ENV JAVA_HOME /path/to/java/dirent
#env java_home /path/to/java/dirent

9、ADD(从src复制文件到container的dest路径)
add 解压

bash 复制代码
ADD <src> <dest>
	<src>是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件url;
	<dest>是container中的绝对路径

10、COPY(从src复制文件到container的dest路径)
copy不解压

bash 复制代码
COPY <src> <dest>

11、VOLUME(指定挂载点):

设置指令,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用。我们知道容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令

bash 复制代码
FROM base
VOLUME ["/tmp/data"]

12、WORKDIR(切换目录):设置指令,可以多次切换(相当于cd命令),对RUN,CMD,ENTRYPOINT生效

bash 复制代码
WORKDIR /p1 WORKDIR p2 RUN vim a.txt
#等同于
run cd  /p1/p2 && vim a.txt

13、ONBUILD(在子镜像中执行):

ONBUILD指定的命令在构建镜像时并不执行,而是在它的子镜像中执行

bash 复制代码
ONBUILD ADD./app/src
ONBUILD RUN /usr/local/bin/python-build--dir /app/src

创建一个tomcat的dockfile

bash 复制代码
[root@localhost ~]$ cat Dockerfile
FROM hub.c.163.com/public/centos:6.7  #基础镜像
MAINTAINER wangyang@itxdl.cn   #坐着信息

ADD ./apache-tomcat-7.0.42.tar.gz /root  #复制文件到容器内
ADD ./jdk-7u25-linux-x64.tar.gz /root

ENV JAVA_HOME /root/jdk1.7.0_25   #设置环境变量
ENV PATH $JAVA_HOME/bin:$PATH

EXPOSE 8080  #开放端口

ENTRYPOINT /root/apache-tomcat-7.0.42/bin/startup.sh && tailf /root/apache-tomcat-7.0.42/logs/catalina.out   #执行命令




#dockerfile转换成镜像
[root@localhost ~]$ docker build -t tomcat:v1.0 .


#镜像转换成容器
[root@localhost ~]$ docker run --name tomcat -p 80:8080 tomcat:v1.0

命令不能超过128行

4.4 镜像的导出以及导入

bash 复制代码
导出:docker save -o xx.xx.xxxx.xx.xx.tar
导入:docker load -i xx.xx.xx.tar

五、镜像仓库构建

5.1 官方仓库构建方式

仓库服务器配置:

bash 复制代码
[root@localhost ~]$ docker run -d -v /opt/registry:/var/lib/registry -p 5000:5000 --restart=always registry

[root@localhost ~]$ vim /etc/docker/daemon.json
{
	"insecure-registries":["10.10.10.11:5000"]
}

客户机设置:

bash 复制代码
[root@localhost ~]$ vim/etc/sysconfig/docker
{
  "registry-mirrors": [
    "https://docker.ims.run",
    "https://ims.run/"
  ],
  "insecure-registries": [
    "10.10.10.11:5000"
  ]
}
#增加
curl -XGET http://10.10.10.11:5000/v2/_catalog 
#查看已有镜像

5.2 Harbor构建

https://www.yuque.com/office/yuque/0/2020/pdf/393192/1603727507994-60aba29a-b8fc-4b89-ab0c-323cc94e7dd0.pdf?from=https%3A%2F%2Fwww.yuque.com%2Fmo_ming%2Fgl7b70%2Fyixtbh

docker报错ERROR: client version 1.22 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version

这个问题其实是你docker-compose.yaml中

vim /root/software/harbor/docker-compose.yaml

把原来version: '2'改成version: '2.1'就可以了

六、Docker中的网络

6.1 Linux 内核中的 NameSpace

namespace 系统调用参数 隔离内容 内核版本
UTS CLONE_NEWUTS 主机名和域名 2.6.19
IPC CLONE_NEWIPC 信号量、消息队列和共享内存 2.6.19
PID CLONE_NEWPID 进程编号 2.6.24
NetWork CLONE_NEWNET 网络设备、网络栈、端口等 2 .6.29
Mount CLONE_NEWNS 挂载点(文件系统) 2.4.19
User CLONE_NEWUSER 用户和用户组 3.8

6.2 Docker网络通讯示意图

容器与容器之间通过namespace进行隔离,隔离为两端,一端放在容器内部,充当eth0网卡,另一端放在宿主机上进行连通,不同容器之前通过docker0网桥进行通信

6.3 Docker中的防火墙规则

容器访问外部网络(防火墙nat转换)

bash 复制代码
#防火墙的nat转换
[root@localhost ~]$ iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o docker0 -j MASQUERADE





-t nat	指定操作的 iptables 表为nat表(网络地址转换表),专门处理 IP / 端口的转换,Docker 网络的地址伪装、端口映射都依赖这个表
-A POSTROUTING	-A是 ** 追加(Append)** 规则到指定链,POSTROUTING是 nat 表的出站链,数据包离开本机网卡前会经过这个链,是做源地址转换(SNAT/MASQUERADE)的核心链
-s 172.17.0.0/16	匹配源 IP为 172.17.0.0/16 网段的数据包(这是 Docker 默认的桥接网络网段,所有默认桥接的容器都会分配这个网段的 IP)
-o docker0	匹配 ** 出站网卡(Output)** 为docker0的数据包(docker0是 Docker 创建的默认网桥,容器默认桥接到此网卡,与宿主机互通)
-j MASQUERADE	-j是跳转(Jump)到指定目标动作,MASQUERADE是动态源地址伪装,属于 SNAT(源地址转换)的特殊形式,会将数据包的源 IP 替换为出站网卡(docker0)的 IP,让外部网络认为数据包来自宿主机的 docker0 网卡,而非容器的私有 IP

外部网络访问容器(dnat转换)

bash 复制代码
[root@localhost ~]$ docker run -d -p 80:80 apache


这是创建并启动 Apache 容器的基础命令,核心是端口映射,各参数作用:
-d:后台运行容器(守护进程模式),不会占用当前终端;
-p 80:80:宿主机端口:容器端口的映射规则,将宿主机的 80 端口,转发到容器内的 80 端口(Apache 默认监听 80 端口);
apache:基于官方apache镜像创建容器,Docker 会自动拉取镜像(本地无的话)。

执行后 Docker 会做两件核心事:
为容器分配私有 IP(示例中是 172.17.0.2,属于 docker0 网桥的 172.17.0.0/16 网段);
自动在 iptables 的 nat 表中添加你后续手动执行的这两条转发规则(这是 Docker 端口映射的底层实现,无需手动写,这里手动执行是复现 Docker 的自动操作)。

iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL-j DOCKER

-t nat	操作 nat 表(网络地址转换表),端口映射属于目标地址转换(DNAT),必须用 nat 表;
-A PREROUTING	追加规则到 PREROUTING 链,数据包进入本机网卡后、路由决策前会经过此链,是 DNAT 的核心链(所有外部 / 本地对宿主机端口的请求,都会先走这里);
-m addrtype --dst-type LOCAL	加载addrtype匹配模块,匹配 ** 目标地址类型为本地(LOCAL)** 的数据包(包括宿主机的公网 IP、内网 IP、127.0.0.1 回环地址,简单说:所有访问宿主机自身 IP / 端口的请求,都符合这个条件);
-j DOCKER	将匹配的数据包跳转到Docker 自定义的 DOCKER 链(Docker 启动时会自动创建这个链,专门存放所有端口映射的转发规则,避免和系统原有规则混淆)。


iptables -t nat -A DOCKER !-i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80

-A DOCKER	追加规则到 Docker 自定义的DOCKER链(承接规则 1 的跳转,做具体转发);
! -i docker0	关键:!是 "非" 的意思,-i是匹配入站网卡(Input);整体表示「匹配不是从 docker0 网卡进入的数据包」(避免容器之间访问宿主机端口时重复转发,造成网络环路);
-p tcp -m tcp	先指定协议为 TCP,再加载 tcp 匹配模块(精细化匹配 TCP 协议的特征,如端口);
--dport 80	匹配目标端口为 80 的数据包(即访问宿主机 80 端口的请求);
-j DNAT	跳转执行目标地址转换(DNAT),修改数据包的目标 IP 和端口,是端口映射的核心动作;
--to-destination 172.17.0.2:80	DNAT 的目标地址:将数据包的目标 IP 改为容器私有 IP 172.17.0.2,目标端口改为 80(容器内 Apache 的监听端口)。

6.4 Docker网络的修改

Docker进程网络修改

  • b,--bridge=""指定Docker使用的网桥设备,默认情况下Docker会自动创建和使用docker0网桥设备,通过此参数可以使用已经存在的设备
  • --bip指定Docker0的IP和掩码,使用标准的CIDR形式,如10.10.10.10/24
  • dns配置容器的DNS,在启动Docker进程是添加,所有容器全部生效

Docker容器网络修改

  • -- dns用于指定启动的容器的DNS
  • --net用于指定容器的网络通讯方式,有以下四个值
    • bridge:Docker默认方式,网桥模式
    • none:容器没有网络栈
    • container:使用其它容器的网络栈,Docker容器会加入其它容器的network namespace
    • host:表示容器使用Host的网络,没有自己独立的网络栈。容器可以完全访问Host的网络,不安全

6.5 端口的暴露方式

- p/P选项的使用格式

bash 复制代码
-p : <ContainerPort>:将制定的容器端口映射至主机所有地址的一个动态端口
-p <HostPort>:<ContainerPort>:映射至指定的主机端口
-p <IP>::<ContainerPort>:映射至指定的主机的IP的动态端口
-p <IP>:<HostPort>:<ContainerPort>:映射至指定的主机IP的主机端口
-P(大):暴露所需要的所有端口



[root@localhost ~]$ docker port ContainerName #可以查看容器当前的映射关系

6.6 网络隔离

基础命令说明

bash 复制代码
#查看当前可用的网络类型
[root@localhost ~]$ docker network ls

#类型网络空间名称
[root@localhost ~]$ docker network create -d 类型 网络空间名称
#类型分为:
	overlay
	bridge

使用网络名字空间进行隔离代码记录

bash 复制代码
[root@localhost ~]$ docker network create -d bridge --subnet "172.26.0.0/16" --gateway "172.26.0.1" my-bridge-network

[root@localhost ~]$ docker run -d --network=my-bridge-network --name test1 hub.c.163.com/public/centos:6.7-tools

[root@localhost ~]$ docker run -d --name test2 hub.c.163.com/public/centos:6.7-tools

使容器配置上独立IP进行通讯

  1. 配置真实网桥
bash 复制代码
[root@localhost ~]$ cd /etc/sysconfig/network-scripts

cp -a ifcfg-ens33 ifcfg-br0

[root@localhost ~]$ vi ifcfg-eth0
DEVICE=eth0
HWADDR=00:0C:29:06:A2:35
TYPE=Ethernet
UUID=34b706cc-aa46-4be3-91fc-d1f48c301f23
ONBOOT=yes
BRIDGE=br0
NM_CONTROLLED=yes
BOOTPROTO=static



[root@localhost ~]$ vi ifcfg-br0
#改成这样
TYPE=Bridge
NAME=br0
DEVICE=br0
ONBOOT=yes
BOOTPROTO=static
IPADDR=10.10.10.17
GATEWAY=10.10.10.2
DNS1=8.8.8.8
DNS2=114.114.114.114
  1. 使用工具分配地址
bash 复制代码
[root@localhost ~]$ yum install -y git

[root@localhost ~]$ git clone https://github.com/jpetazzo/pipework

[root@localhost ~]$ cp pipework/pipework/usr/local/bin/

[root@localhost ~]$ docker run -itd --net=none --name=ff centos-6-x86 bash

[root@localhost ~]$ pipework br0 fl 192.168.216.135/24

七、数据存储

7.1 数据卷特性

  • Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层
  • 如果运行中的容器修改了现有的一个已经存在的文件,那么该文件将会从读写层下面的的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,次即"写时复制"机制

7.2 数据卷的意义

  • Volume可以在运行容器时即完成创建与绑定操作。当然,前提需要拥有对应的申明
  • Volume的初衷就是数据持久化

7.3 数据卷的类型

  • Bind mount volume
  • Docker-managed volume

7.4 容器中使用数据卷的方法

Docker-managed Volume(自动绑定)

bash 复制代码
[root@localhost ~]$ docker run -it --name roc -v MOUNTDIR roc/lamp:v1.0
[root@localhost ~]$ docker inspect -f {{.Mounts}} roc

Bind-mount Volume(手动绑定)

bash 复制代码
[root@localhost ~]$ docker run -it --name roc -v HOSTDIR:VOLUMEDIR roc/lamp:v1.0

Union Volume(联合卷-共享自动绑定)

bash 复制代码
[root@localhost ~]$ docker run -it --name roc --volumes-from ContainerName roc/lamp:v1.0

7.5 存储驱动

Docker存储驱动(storage driver)是Docker的核心组件,它是Docker实现分成镜像的基础

  • device mapper(DM):性能和稳定性存在问题,不推荐生产环境使用
  • btrfs:社区实现了btrfs driver,稳定性和性能存在问题
  • overlayfs:内核3.18overlayfs进入主线,性能和稳定性优异,第一选择
bash 复制代码
[root@localhost ~]$ mount -t overlay overlay -o lowerdir=./low,upperdir=./upper,workdir=./work ./merged





[root@localhost overlay] tree .
.
├── low            #最底层
│   └── 1.txt
├── merged         #用户展示层
│   ├── 1.txt
│   └── 2.txt
├── upper          #中间层
│   └── 2.txt
└── work           #工作层
    └── work

修改为overlayfs存储驱动

bash 复制代码
[root@localhost ~]$ echo "overlay" > /etc/modules-load.d/overlay.conf
[root@localhost ~]$ cat /proc/modules|grep overlay
[root@localhost ~]$ reboot
[root@localhost ~]$ vim /etc/systemd/system/docker.service
	storage-driver=overlay\

八、资源限制

8.1 内存资源限制

相关说明

  • CGroup是Control Groups的缩写,是Linux内核提供的一种可以限制、记录、隔离进程组(process groups)所使用的物力资源(如cpu memory i/o等等)的机制。2007年进入Linux2.6.24内核,CGroups不是全新创造的,它将进程管理从cpuset中剥离出来,作者是Google的Paul Menage
  • 默认情况下,如果不对容器做任何限制,容器能够占用当前系统能给容器提供的所有资源
  • Docker限制可以从Memory、CPU、BlockI/O三个方面
  • OOME:Out Of Memory Exception
    • 一旦发生OOME,任何进程都有可能被杀死,包括docker daemon在内
    • 为此,Docker调整了docker daemon的OOM优先级,以免被内核关闭

重点提示

  • 为应用做内存压力测试,理解正常业务需求下使用的内存情况,然后才能进入生产环境使用
  • 一定要限制容器的内存使用上限
  • 尽量保证主机的资源充足,一旦通过监控发现资源不足,就进行扩容或者对容器进行迁移
  • 如果可以(内存资源充足的情况),尽量不要使用swap,swap的使用会导致内存计算复杂,对调度器非常不友好

8.2 内存限制设置方式

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

bash 复制代码
-m --memory:容器能使用的最大内存大小,最小值为4m

--memory-swap:容器能够使用的swap大小

--memory-swappiness:默认情况下,主机可以把容器使用的匿名页(anonymouspage)swap出来,你可以设置一个0-100之间的值,代表允许swap出来的比例

--memory-reservation:设置一个内存使用的softlimit,设置值小于--m设置

--kernel-memory:容器能够使用的kernelmemory大小,最小值为4m。

--oom-kill-disable:是否运行OOM的时候杀死容器。只有设置了-m,才可以把这个选项设置为false,否则容器会耗尽主机内存,而且导致主机应用被杀死

8.3 参数示意图

8.4 CPU资源限制

Docker提供的CPU资源限制选项可以在多核系统上限制容器能利用哪些vCPU。而对容器最多能使用的CPU时间有两种限制方式:

  • 一是有多个CPU密集型的容器竞争CPU时,设置各个容器能使用的CPU时间相对比例
  • 二是以绝对的方式设置容器在每个调度周期内最多能使用的CPU时间

CPU限制方式

bash 复制代码
[root@localhost ~]$ docker run -it --cpu-period=50000 --cpu-quota=25000 ubuntu:16.04 /bin/bash
[root@localhost ~]$ docker run -it --cpu-period=10000 --cpu-quota=20000 ubuntu:16.04 /bin/bash

--cpuset-cpus=""     允许使用的CPU集,值可以为0-3,0,1

-c,--cpu-shares=0    CPU共享权值(相对权重),默认值1024

--cpuset-mems=""     允许在上执行的内存节点(MEMs)

--cpu-period=0       即可设置调度周期,CFS周期的有效范围是1ms~1s,对应的--cpu-period的数值范围是1000~1000000

--cpu-quota=0        设置在每个周期内容器能使用的CPU时间,容器的CPU配额必须不小于1ms,即--cpu-quota的值必须>=1000,单位微秒

--cpus                能够限制容器可以使用的主机CPU个数,并且还可以指定如1.5之类的小数

8.5 限制性实验

bash 复制代码
[root@localhost ~]$ docker run --name stress -it --rm -m 256m lorel/docker-stress-ng:latest stress-ng --vm 2

启动一个临时的、限制 256MB 内存的 stress-ng 容器,用 2 个进程执行内存压力测试,容器退出后自动删除

docker run	Docker 核心命令,创建并启动一个新容器
--name stress	给容器命名为stress,方便后续通过docker ps/kill stress操作容器
-it	组合参数:-i保持标准输入打开,-t分配伪终端,保证能看到压测实时输出
--rm	容器停止 / 退出后自动删除容器,避免产生无用的僵尸容器,适合临时压测
-m 256m	限制容器的可用内存上限为 256MB(m=MB),超出后容器会被 OOM 杀死 / 限制
lorel/docker-stress-ng:latest	压测使用的基础镜像,已预装stress-ng压力测试工具,无需自己安装
stress-ng	容器内执行的核心压测命令,是 Linux 主流的多维度压力测试工具(CPU / 内存 / 磁盘等)
--vm 2	stress-ng 的内存压测参数:启动2 个内存分配进程,持续申请 / 释放内存压测

[root@localhost ~]$docker run --name stress -it --rm --cpus 2 lorel/docker-stress-ng:latest stress-ng --cpu 8

创建一个临时容器,限制其最多使用宿主机 2 个 CPU 核心,同时启动 8 个 CPU 密集型压测进程,让这 8 个进程竞争 2 核 CPU 资源,打满容器的 CPU 配额

--cpus 2	核心限制:Docker 给容器分配2 个 CPU 核心的计算能力,容器内所有进程的 CPU 使用率总和最大为 200%(宿主机top中看容器进程会体现)
stress-ng --cpu 8	启动8 个 CPU 压测进程(每个进程做纯计算密集型操作,比如循环计算)
其余--name/-it/--rm	与之前一致:命名容器、分配终端看实时输出、容器退出后自动删除

[root@localhost ~]$ docker run --name stress -it --rm --cpuset-cpus 0 lorel/docker-stress-ng:latest stress-ng --cpu 8

容器被强制限定只能使用宿主机第 0 号 CPU 核心,无法使用其他任何核心,8 个 CPU 压测进程在这颗核心上竞争运行,将其 100% 打满

--cpuset-cpus 0	精准 CPU 核心绑定:容器内所有进程只能运行在宿主机第 0 号物理 CPU 核心,完全隔离其他核心;支持多核心绑定,如0,1(0 和 1 核)、0-2(0/1/2 核)
--cpu 8	启动 8 个 CPU 密集型压测进程(循环计算),竞争--cpuset-cpus 0绑定的单核资源
--name/-it/--rm	容器命名为 stress、分配终端看实时输出、退出后自动删除,与之前一致
stress/stress-ng	前者是软链兼容旧版,后者是镜像原生命令,推荐用后者

核心逻辑	容器只能跑在指定物理核心,独占 / 竞争该核心的 100% 资源,无法使用其他核心	容器可跨宿主机所有 CPU 核心运行,只是总计算能力被限制为 1 个核心(100%)
资源隔离性	极高:容器进程不会跑到其他核心,适合需要物理核心隔离的场景(如性能测试、独占资源)	较低:进程会被 Docker 调度到不同核心,只是总使用率被限流,适合普通的资源限制
宿主机 CPU 显示	宿主机top中只有第 0 号核心的使用率会拉满到 100%,其他核心不受影响	宿主机top中多个核心会分摊使用率(比如 2 个核心各 50%),总和接近 100%
适用场景	精准性能测试、核心独占、容器间 CPU 隔离、排查单核心性能问题	普通业务容器的 CPU 限流、不关心物理核心分布,只限制总计算能力



--cpuset-cpus是绑「物理核心」,--cpus是限「计算能力」,你的这条命令用--cpuset-cpus 0,会让宿主机仅第 0 核被打满,其他核心完全空闲,这是和之前--cpus 2最本质的区别。

# 新开一个终端执行,实时查看容器资源
docker stats stress
相关推荐
Java陈序员1 天前
轻量强大!一款现代化的 Kubernetes 集群管理与监控工具!
云原生·容器·kubernetes
爱吃橘子橙子柚子2 天前
3CPU性能排查总结(超详细)【Linux性能优化】
运维·cpu
Sheffield3 天前
Docker的跨主机服务与其对应的优缺点
linux·网络协议·docker
Sheffield3 天前
Alpine是什么,为什么是Docker首选?
linux·docker·容器
马艳泽3 天前
win10下运行Start Broker and Proxy报错解决
docker
舒一笑4 天前
程序员效率神器:一文掌握 tmux(服务器开发必备工具)
运维·后端·程序员
NineData4 天前
数据库管理工具NineData,一年进化成为数万+开发者的首选数据库工具?
运维·数据结构·数据库
用户13573999256604 天前
Windows 从 0 搭建 WSL2 原生 AI 开发环境:Codex + Docker + VSCode
docker
vi_h4 天前
在 macOS 上通过 Docker 安装并运行 Ollama(详细可执行教程)
macos·docker·ollama
黑心老魔4 天前
通过 Docker 创建开发环境
docker·开发环境