文章目录
- 一、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
非阿里云的产品加速镜像并不适用
推荐:
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构建
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进行通讯
- 配置真实网桥
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
- 使用工具分配地址
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