一、docker的安装和卸载
二、更换阿里容器镜像仓库,加快镜像下载速度
三、Docker的基本使用
四、Dockerfile制作镜像
五、Dockerfile创建的镜像当做虚拟机使用
六、docker-compose
七、docker-compose的安装
八、docker-compose的使用
九、docker-compose的CLI环境变量
十、docker-compose中的环境变量
十一、docker-compose的容器编排技术

======================================

一、docker的安装和卸载
  默认/var/lib/docker/目录下面存放Docker的镜像、容器、卷、网络文件,保证/var/所在容量大于40G
  Docker容器其实就是一个进程
  自2017年3月份 Docker 公司把 Docker 划分为了社区版和企业版
Docker Community Edition(CE)  为社区版, 免费
  Docker CE有两个更新通道,稳定和开发:
  Stable每季度为您提供可靠的更新
  Edge每个月都会为您提供新功能。
Docker Enterprise Edition 为企业版, 收费
  支持安全扫描,LDAP集成,内容签名,多云支持等

1、下载Docker仓库
wget https://download.docker.com/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo

2、安装Docker引擎,docker-ce
yum install -y docker-ce docker-ce-cli containerd.io

3、启动和开机自启Docker
systemctl start docker && systemctl enable docker

4、通过运行Docker最小镜像hello-world来验证Docker是否安装成功
docker run hello-world
  本地没有镜像就会从官方镜像仓库Docker Hub拉取,这个镜像没有什么实际意义,只是用来检测Docker服务环境是否正常,正常的话会在拉取玩镜像后打印出,Hello from Docker! 证明Docker Engine安装成功

docker -v查看docker版本
docker info查看docker状态

5、卸载Docker
卸载Docker Engine,CLI和Containerd软件包
yum remove docker-ce docker-ce-cli containerd.io
删除所有的镜像、容器和卷
rm -rvf /var/lib/docker

6、使用非 root 用户管理 docker
  Docker守护进程绑定到Unix套接字而不是TCP端口。默认情况下,Unix套接字是归 root 用户所有,其他用户只能使用 sudo 的方式访问它。
  Docker守护进程始终以 root 用户身份运行。如果您不想在 docker 命令前面加 sudo,请创建一个名为 docker 的组(centos 中 这个组已经存在)并向其中添加用户。
  当Docker守护进程启动时,它会创建一个Unix套接字,供Docker组的成员访问

二、更换阿里容器镜像仓库,加快镜像下载速度
  https://www.aliyun.com/~登录~搜索容器镜像服务~镜像加速器~按照文档配置/etc/docker/daemon.json,每个用户都会有自己专有的链接

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-‘EOF’
{
“registry-mirrors”: [“https://vd3mapah.mirror.aliyuncs.com”]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

镜像加速器
  使用 Docker 的时候,需要经常从官方获取镜像,但是由于显而易见的网络原因,拉取镜像的过程非常耗时,严重影响使用 Docker 的体验。因此 DaoCloud(企业级别容器云平台)推出了加速器工具解决这个难题,通过智能路由和缓存机制,极大提升了国内网络访问 Docker Hub 的速度,目前已经拥有了广泛的用户群体,并得到了 Docker 官方的大力推荐

三、Docker的基本使用(注意区别对容器的操作和对镜像的操作)

1、Docker命令语法
docker   run  -itd centos:7
    子命令 选项 镜像名称:标签
  假如运行的镜像不在本地,会自动从 Docker hub 下载到本地,之后再运行,不加标签默认标签tag为最新latest
• -i 表示持续和容器交互,防止断开
• -t 分配一个伪tty终端,以便和容器进行命令的交互
• -d 容器后台运行

2、运行Centos7镜像
docker run -it centos:7
  run子命令后面跟的是镜像名,run命令相当于用镜像创建一个容器,-d参数可以让run创建的容器为后台运行状态(up),不加-d参数,会直接进入run创建的容器,exit退出后,容器状态为停止状态(exited)
  run通过镜像创建容器的时候最好给容器起一个辨识度高、好记、有意义的名字,如果不起名,系统随机起名
docker run -itd --name 容器名称 centos:7
  如果在使用Docker时有自动化的需求,你可以将containerID输出到指定的文件中(PIDfile)类似于某些应用程序将自身ID输出到文件中,方便后续脚本操作。
–cidfile="": Write the container ID to the file

3、查看本地镜像
docker images 或者 docker image ls
查看镜像详情
inspect 英 [ɪnˈspekt] 美 [ɪnˈspekt] v.检查;查看;审视;视察
docker image inspect 镜像id

4、搜索镜像
docker search centos 查看centos的所有镜像

docker search redis --limit 2
支持模糊匹配,一般第一个就是官方的,Docker官方或者相关应用官方
–limit 2 只显示前两个

5、拉取镜像到本地
pull默认拉取search的第一个
docker pull 仓库名[:标签]
docker pull centos:8
Pulling from library/centos 仓库名采用两段式<用户名>/<镜像名>,默认用户名是library即官方镜像
镜像是分层的,一层一层的拉取

6、删除本地镜像
删除一个或多个,多个之间用空格隔开,可以使用镜像名称或id
docker image rm hello-world(新命令)
docker rmi hello-world(旧命令)
docker rmi 仓库名(镜像名):标签/唯一标识的镜像ID
强制删除:–force
如果镜像正在被使用中可以使用–force强制删除
docker rmi hello-world --force
只查看所有镜像的id
docker images -q
删除所有的镜像
docker rmi $(docker images -q)
-q查出所有id号

7、查看所有容器
docker ps -a
只查看所有容器id:
docker ps -a -q
列出最近一次启动的容器
docker ps -l
查看容器详情
docker inspect 容器/ID

8、查看运行状态的容器
docker ps

9、启动/重启一个已经停止的容器
docker start 容器ID/容器名称
docker restart 容器ID/容器名称
  容器ID不必写全,只要保证可以识别到唯一的容器即可,但容器ID并不方便,所以最好给每一个run创建的容器起一个辨识度高的name名字

10、停止一个正在运行的容器
docker stop 容器ID/容器名称

11、进入和退出一个正在运行的容器(如果容器停止,需要先启动)
docker attach 容器ID/容器名称
attach方式进入容器,exit退出后会导致容器的状态为退出终止(和run一样),因为当使用docker attach命令进入容器时,执行的是容器自带的命令,把容器默认进程杀掉,容器自然终止
docker exec -it 容器ID/容器名称 bash(容器内的命令)
  进入一个正在运行的容器需要执行一个容器内的命令
docker exec进入容器,exit退出后对容器的状态不会产生影响
退出容器:exit

12、删除一个已经停止的容器
删除正在运行容器–force/-f
docker rm 容器ID/容器名称 --force
docker rm 容器ID/容器名称
删除已经停止的全部容器(或者删除其他状态的容器)
首先 -f 参数过滤出是退出状态的容器,注意小写(-f 相当于管道命令)
docker ps -a -f status=exited
然后 -q 参数只显示容器id
docker ps -aq -f status=exited
最后$()或者``预先执行后删除
docker rm docker ps -aq -f status=exited
docker rm $(docker ps -aq -f status=created)

13、镜像的保存和加载(镜像迁移)
有时由于环境原因有些机器无法拉取镜像,可以使用Docker的保存和加载机制,把镜像复制到任意服务器。保存一台宿主机上的镜像为tar文件,然后可以导入到其他的宿主机上。
docker images
docker save centos:8 > centos-8.tar
ls可以在当前目录看到centos-8.tar,扩展名重要名字随意,将其拷贝到目标服务器
docker load < centos-8.tar
docker images

14、容器的导出和导入
  将容器的文件系统打包成tar文件,也就是把正在运行的容器直接导出为tar包的镜像文件
docker ps -a
docker run -itd --name ubuntu ubuntu:latest
docker export ubuntu > ubuntu.tar
ls可以咋在当前目录看到ubuntu.tar,扩展名重要名字随意,将其拷贝到目标服务器
docker import ubuntu.tar
  如果导入镜像时没有起名字,随后可以单独起名字(没有名字和tag),可以手动加tag
注意,import命令是将容器快照导入为的镜像
docker images
docker tag a52ae06e1441 centos:7
tag加的镜像ID,给新import的镜像加上仓库名和标签,重复操作不会覆盖,会新建
(docker tag centos:7 sun:8)
docker run -it --rm sunlizhen bash 自己导入的镜像,run后面跟一个命令

注:
1.tar文件的名称和保存的镜像名称没有关系
2.导入的镜像如果没有名称,自己打tag起名字
扩展:export和save的区别
export:相当于容器快照,容器快照文件将丢弃所有的历史记录和元数据信息
save:没有这个现象,就是完整的

15、直接通过容器创建本地镜像
  容器运行起来后,又在里面做了一些操作,并且要把操作结果保存到镜像里
  使用 docker commit 指令,把一个正在运行的容器,直接提交为一个镜像。commit 是提交的意思,类似告诉svn服务器我要生成一个新的版本。
commit 英 [kəˈmɪt] 美 [kəˈmɪt] v承诺,保证(做某事、遵守协议或遵从安排等)

docker run -itd --name ng-commint nginx /bin/bash
docker exec -it ng-commint bash
在docker中做改动
mkdir /mnt/sunlizhen
exit
docker ps
docker commit ng-commint
docker images
会看到本地镜像仓库中多了一个标签的镜像
docker tag 镜像ID ng-commit:7
docker images
docker run -it ng-commit:7 /bin/bash
创建的目录还在

docker commit的参数
docker commit -m “my images version1” -a “kakaops” ng-commit image1:7

docker images
image1 7 6d1480d847bb 8 seconds ago 133MB

16、本地文件和容器文件快速交换(cp拷贝和scp格式一样)
将本地的文件 a.txt 拷贝到容器的 /root/ 目录下,反之亦然
docker cp a.txt 容器ID/容器名称:/mnt/

17、挂载本地文件/目录到容器
要求root操作,可以实现配置文件的双向同步更改
docker run -it -v /home/a.txt:/tmp/a.txt centos:7
• -v 本地文件路径,这个路径必须是绝对路径
只能run的时候挂挂载
docker run -itd --name sunlizhen -v /mnt/sun.txt:/tmp/a.txt ubuntu:latest

18、后台运行映射容器端口到本地端口
docker run -d   -p   8000:80    nginx
   运行在后台 映射端口 本地端口:容器端口 镜像名称
不执行命令也就没有必要 -t 分配一个伪终端
不进入容器也就没有必要 -i 持续交互
都写也可以
docker run -itd -p 8000:80 nginx
访问本地的8000端口,可以看到nginx服务 -I 只看响应头
curl -I 127.0.0.1:8000

18、容器交互模式启动容器,容器内执行/bin/bash命令

19、注意事项:
1、后台模式创建的容器,exec进入的容器,exit退出,容器仍然会处于up状态
2、交互模式创建的容器,exit退出,容器会处于exited状态,退出不关闭:快捷键:ctrl+p+q

四、Dockerfile制作镜像
docker build命令语法
docker build命令用于根据给定的Dockerfile和上下文以构建Docker镜像。
docker build语法:
docker build [OPTIONS] <PATH | URL | ->
-f Docker的绝对路径
-t 指定镜像名称和标签

1、docker build常用选项说明
–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。设置该选项,将新构建出的多个层压缩为一个新层,但是将无法在多个镜像之间共享新层;设置该选项,实际上是创建了新image,同时保留原有image。
–tag, -t,镜像的名字及tag,通常name:tag或者name格式;可以在一次构建中为一个镜像设置多个tag
–network,默认default。设置该选项,Set the networking mode for the RUN instructions during build
–quiet, -q ,默认false。设置该选项,Suppress the build output and print image ID on success
–force-rm,默认false。设置该选项,总是删除掉中间环节的容器
–rm,默认–rm=true,即整个构建过程成功后删除中间环节的容器

2、<PATH | URL | ->命令上下文说明
给出命令执行的上下文。
  上下文可以是构建执行所在的本地路径,也可以是远程URL,如Git库、tarball或文本文件等。如果是Git库,如https://github.com/docker/rootfs.git#container:docker,则隐含先执行git clone --depth 1 --recursive,到本地临时目录;然后再将该临时目录发送给构建进程。
构建镜像的进程中,可以通过ADD命令将上下文中的任何文件(注意文件必须在上下文中)加入到镜像中。
-表示通过STDIN给出Dockerfile或上下文。

3、闫哥教的Dockerfile基本使用
  镜像里面通常只有一些基本命令,但有时候部署应用需求要在容器里面预装一些软件,和进行一些初始化配置,可以编辑一个Dockerfile文件来实现(默认文件名不能变,就是Dockerfile,当然也可以加参数指定)
mkdir centos7
cd centos7/
vim Dockerfile
FROM centos:7       #创建的镜像以哪一个镜像为基础,本地有这个基础镜像就直接用,没有会先拉取
RUN yum install -y \     #以centos:7镜像为基础创建一个容器,之后执行容器里面的命令
vim bash-com* openssh-clients openssh-server iproute cronie;
yum group install -y “Development Tools”;yum clean all;
localedef -c -f UTF-8 -i zh_CN zh_CN.UTF-8 &&
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENV LANG=zh_CN.UTF-8  #设置环境变量,让容器支持中文
#只安装需要的软件和进行必须要的设置,容器瘦身
#命令之间要用分号隔开
bash-com*(自动命令补全) openssh-clients(保证有ssh命令) openssh-server(保证有sshd服务) iproute(保证有ip a和ss命令) cronie(计划任务服务)
Development Tools安装一组编译安装需要的开发环境
yum clean all缓存清除,保证容器最小
FROM、RUN、ENV叫做Dockerfile的指令,每执行一个Dockerfile指令,镜像增加一层(指令尽量少)

编写完Dockerfile文件后build构建镜像仓库
docker build . -t centos7-sshd
. 表示在当前目录去寻找Dockerfile文件 -t 指定了构建后的镜像名称
如果成功会有下面提示
Successfully built d83a8a429831
Successfully tagged centos7-sshd:latest
docker run -itd --name h5 --rm centos7-sshd
–rm 的作用是容器退出后自动删除

Dockerfile指令总结
1、关于执行命令方面
RUN:构建一个镜像时,在基础容器镜像中执行的命令,并提交结果。每个RUN指令都会给目前正在创建的镜像增加一层
CMD:当使用一个镜像运行作为一个容器的时候的默认运行命令,CMD指令在构建时不进行任何操作,只是为运行容器的时候提供一个默认指令。一个镜像中只能有一个CMD指令,多个的话最后一个生效。其指定的命令可以被运行一个容器时候指定的命令所覆盖
比如镜像中的 CMD 为:CMD ["/bin/bash"]
假设运行容器时:
docker run -it centos:7 ls /tmp 那就是执行 ls /tmp 命令
ENV:设置环境变量

2、关于文件方面
COPY和ADD:两者都是把宿主机的文件复制到容器中
COPY:官方推荐,源路径支持通配符,保留源文件的元数据
ADD:支持自动解压,但是会导致构建镜像时的缓存失效,从而影响构建的效率

3、关于容器数据持久化方面
关于使用数据卷和挂载主机目录的提示
  如果将空卷挂载到容器中的含有内容的目录中,则会将这些内容复制到卷中。同样,如果您启动容器并指定一个尚不存在的卷,则会为您创建一个空卷。
  如果将一个bind mount 或非空的数据卷挂载到容器中的一个非空目录中,则这些内容会被遮盖隐藏。隐藏的内容不会被删除或更改,此时也不可被访问。就像在 Linux 机器中使用 mount 命令一样的效果

五、Dockerfile创建的镜像当做虚拟机使用
docker exec -it h5 bash方式进入虚拟机,没有权限不能执行systemctl命令,因为容器仅仅只是真正宿主机的一个进程而已,没有权限,需要特权模式run一个容器
docker run -itd --name h9 --rm --privileged=true centos7-sshd /usr/sbin/init
–privileged=true 特权模式
/usr/sbin/init 执行systemctld1号进程的命令

六、docker-compose
compose英 [kəmˈpəʊz] 美 [kəmˈpoʊz]
v.组成,构成(一个整体);作曲;创作(音乐);撰写
  Compose是用于定义和运行多容器Docker应用程序的工具。通过Compose,可以使用YAML文件来配置应用程序的服务。然后,使用一个命令,就可以从配置中创建并启动所有服务。Compose可在所有环境中工作:生产,登台,开发,测试以及CI工作流。使用Compose基本上是一个三步过程:
  1、使用定义应用环境,Dockerfile以便可以在任何地方复制。
  2、定义组成应用程序的服务,docker-compose.yml 以便它们可以在隔离的环境中一起运行
  3、Run docker-compose upand Compose启动并运行您的整个应用程序。
  Compose 使用一个具有 YAML风格的文件来实现,这个文件一般叫做 docker-compose.yml 。通过编写这个文件来定义一组相互之间有关联的应用容器。
  Compose 中有两个比较重要的概念: 服务service 和 项目 project。
  服务 service
  就是一个应用容器,实际上可以包含多个使用相同镜像运行的容器实例。
  项目 project
  就是包含了多个 service 的一个 docker-compose.yml 文件

七、docker-compose的安装
mac和windows安装docker会自动安装docker-compose,linux特殊

1、 下载docker-compose
curl -L “https://github.com/docker/compose/releases/download/1.27.4/docker-compose-(uname−s)−(uname -s)-(uname−s)−(uname -m)” -o /usr/local/bin/docker-compose

2、/usr/local/bin/docker-compose增加可执行权限
chmod +x /usr/local/bin/docker-compose

3、验证安装
docker-compose version

4、安装docker-compose子命令自动补全
先安装bash自身的子命令补全软件包
yum install bash-completion
再安装docker-compose子命令自动补全
curl -L https://raw.githubusercontent.com/docker/compose/1.27.4/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
测试是否下载成功,echo $?
重新登录,重启
docker-compose p # 连续敲两次 Tab 键
pause port ps pull push

八、docker-compose的使用

1、首先在指定的目录中编辑一个docker-compose.yml文件

docker-compose版本不同会支持不同属性的名字,有的属性必须高版本才有,所以要声明版本。服务名称和容器名称可以不一样。单引,双引无所谓。指令command属性默认就是bash。network,可以给容器定义一个自定义的网络,好处是设置自定义网络后可以直接使用容器名或者服务名进行通讯,不用考虑ip。配置了自定义网络IPv4地址可以不配置。静态ip,子网网络,网关前三位要对应。

2、以后台的方式运行:up -d
  注意:默认情况下,所有的 docker-compose 命令都必须在含有 docker-compose.yml 文件的目录下执行。
  换句话说,执行 docker-compose 命令的时候,需要保证当前目录下有 docker-compose.yml 文件。
docker-compose up -d  //不加-d后台运行,程序阻塞

3、列出当前 docker-compose 管理的所有的容器: ps
docker-compose ps
Name Command State Ports

host1   /bin/bash  Up

4、列出当前 docker-compose 管理的所有的服务: ps --services
docker-compose ps --services
host1

5、执行容器内的命令:exec
docker-compose exec 服务名 命令 [选项]
执行查看ip命令:docker-compose exec host1 hostname -i
172.16.1.10
执行进入容器命令bash:docker-compose exec host1 bash
在容器中执行exit可以退出容器

6、停止/启动容器: stop/start
在不移除容器的情况下停止运行容器:
docker-compose stop 容器名称
docker-compose stop host1
使用“docker compose start 容器名称”重新启动它们
docker-compose start host1

7、移除/删除/销毁容器:down
  down子命令,停止容器并且删除,并删除容器、网络、卷和映像。
默认情况下删除如下内容:
compose 文件中为服务定义的容器
compose 文件中顶级的 networks 定义的网络设备
默认网络,如果使用了
放心,它不会删除 external 使用的外部网络和卷
选项 -v 可以一同删除 compose 文件中定义的卷,默认是不删除的。
docker-compose down
docker-compose down -v

九、docker-compose的CLI环境变量
CLI:command-line interface,命令行界面
CLI环境变量控制Docker Compose命令行行为
DOCKER_ 开头的变量与Docker命令行客户端配置的变量相同。还可以使用环境文件提供其中一些变量
COMPOSE_PROJECT_NAME
  设置项目名称。启动时,此值将与服务名称一起添加到容器中。例如,如果你的项目名称为myapp,它包括两个服务db和web,然后容器名分别为 myapp_db_1和myapp_web_1。设置此选项是可选的。如果未设置此项,则COMPOSE_PROJECT_NAME 默认为basename项目目录。另请参阅-p 命令行选项
COMPOSE_FILE
  指定Compose文件的路径。如果未提供,Compose将查找当前目录中名为 docker-compose.yml的指定文件,然后查找每个父目录,直到找到该名称的文件。此变量支持由路径分隔符分隔的多个Compose文件(在Linux和macOS上,路径分隔符是:在Windows上;)。例如
  COMPOSE_FILE=docker-compose.yml:docker-compose.prod.yml。
  路径分隔符也可以使用COMPOSE_PATH_SEPARATOR 进行自定义。
另请参阅-f 命令行选项。
COMPOSE_API_VERSION
  Docker API仅支持来自报告特定版本的客户端的请求。如果使用 docker-compose 报错:client and server don’t have same version,则可以通过设置此环境变量来解决此错误。设置版本值以匹配服务器版本。设置此变量旨在解决在需要在客户端和服务器版本不匹配的情况下临时运行的情况。例如,如果您可以升级客户端但需要等待升级服务器。使用此变量集和已知的不匹配运行会阻止某些Docker功能正常工作。失败的确切功能取决于Docker客户端和服务器版本。因此,使用此变量集运行仅用作解决方法,并且不受官方支持。如果您遇到运行此设置的问题,请通过升级解决不匹配问题,并在通知支持之前删除此设置以查看问题是否已解决。
DOCKER_HOST
  设置docker守护程序的URL 。与Docker客户端一样,默认为unix:///var/run/docker.sock。
DOCKER_TLS_VERIFY
  设置为空字符串以外的任何内容时,启用与docker守护程序的TLS通信。
DOCKER_CERT_PATH
  配置路径ca.pem,cert.pem以及key.pem用于TLS验证文件。默认为~/.docker。
COMPOSE_HTTP_TIMEOUT
  配置在Compose认为失败之前允许挂起对Docker守护程序的请求的时间(以秒为单位)。默认为60秒。
COMPOSE_TLS_VERSION
  配置哪个TLS版本用于与docker 守护程序进行TLS通信。默认为TLSv1。支持的值是:TLSv1,TLSv1_1,TLSv1_2。
COMPOSE_CONVERT_WINDOWS_PATHS
  在卷定义中启用从Windows样式到Unix样式的路径转换。Windows上的Docker Machine和Docker Toolbox的用户应始终设置此项。默认为0。支持的值:true或1启用false或0禁用。
COMPOSE_PATH_SEPARATOR
  如果设置,COMPOSE_FILE则使用此字符作为路径分隔符分隔环境变量的值。
COMPOSE_FORCE_WINDOWS_HOST
  如果设置,使用量声明短语法解析假设主机路径是Windows路径,即使是撰写基于UNIX的系统上运行。支持的值:true或1启用false或0禁用。
COMPOSE_IGNORE_ORPHANS
  如果设置,Compose不会尝试检测项目的孤立容器。支持的值:true或1启用false或0禁用。
COMPOSE_PARALLEL_LIMIT
  设置Compose可以并行执行的操作数限制。默认值为64,并且可能不会设置为低于2。
COMPOSE_INTERACTIVE_NO_CLI
  如果设置,Compose不会尝试使用Docker CLI进行交互run和exec操作。在上述操作需要CLI的Windows上,此选项不可用。支持:true或1启用false或0禁用。

十、docker-compose中的环境变量
  在多个文件中设置相同的环境变量时,这是Compose用于选择要使用的值的优先级:
  1、docker-compose.yml文件
  2、Shell环境变量
  3、环境文件
  4、Dockerfile
  5、变量未定义

1、在Compose文件中替换环境变量
  可以在Compose文件中使用 shell 中的环境变量来填充值
$ export TAG=v2.0
web:
image: “webapp:${TAG}”

2、在容器中设置环境变量
  使用environment键在服务的容器中设置环境变量 ,就像docker run -e VARIABLE=VALUE …
web:
environment:
- DEBUG=1

3、将环境变量传递给容器
  使用environment键将环境变量从shell直接传递到服务的容器而不是为它们提供值,就像docker run -e VARIABLE …
web:
environment:
- DEBUG
  所述的值DEBUG在容器变量是从值取为在其中撰写运行在shell中的相同变量

4、env_file 配置选项
  使用env_file选项将多个环境变量从外部文件传递到服务的容器,就像docker run --env-file=FILE …
web:
env_file:
- web-variables.env

5、使用docker-compose run设置环境变量
  就像一样docker run -e,可以在一次性容器上设置环境变量docker-compose run -e
  docker-compose run -e DEBUG=1 web python console.py
  也可以通过不给它赋值来从shell传递变量:
  docker-compose run -e DEBUG web python console.py
所述的值DEBUG在容器变量是从值取为在其中撰写运行在shell中的相同变量

6、.env文件
  在Compose文件中引用的任何环境变量的默认值,或在名为 .env 的环境文件中用于配置Compose
$ cat .env
TAG=v1.5

$ cat docker-compose.yml
version: ‘3’
services:
web:
image: “webapp:${TAG}”
  运行时docker-compose up,web上面定义的服务使用图像webapp:v1.5。使用config命令对此进行验证,该命令将已解析的应用程序的配置信息打印到终端:
$ docker-compose config
version: ‘3’
services:
web:
image: ‘webapp:v1.5’
  shell 中的值优先于.env文件中指定的值。如果TAG在shell中设置了不同的值,则image 使用 shell 中的值
$ export TAG=v2.0
$ docker-compose config
version: ‘3’
services:
web:
image: ‘webapp:v2.0’
  在多个文件中设置相同的环境变量时,这是Compose用于选择要使用的值的优先级:
  1、docker-compose.yml文件
  2、Shell环境变量
  3、环境文件
  4、Dockerfile
  5、变量未定义
  在Environment文件和Compose文件上设置相同的环境变量
$ cat ./Docker/api/api.env
NODE_ENV=test

$ cat docker-compose.yml
version: ‘3’
services:
api:
image: ‘node:6-alpine’
env_file:
- ./Docker/api/api.env
environment:
- NODE_ENV=production
  运行容器时,Compose文件中定义的环境变量优先。
$ docker-compose exec api node

process.env.NODE_ENV
‘production’
  NodeJS容器的细节:如果你有一个类似 的package.json条目,那么这将取代你文件中的任何设置。script:start NODE_ENV=test node server.js docker-compose.yml

十一、docker-compose的容器编排技术

1、含有多台主机的 docker-compose.yml
定义一个 Dockerfile
  先定义一个 Dockerfile,我们可以从这个 Dockerfile 中构建一个自定义的镜像,从而获取到一个我们自定义的容器。
FROM centos:7
RUN yum install -y
vim bash-com* openssh-clients openssh-server iproute cronie;
yum group install -y “Development Tools”;yum clean all;
localedef -c -f UTF-8 -i zh_CN zh_CN.UTF-8 &&
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENV LANG=zh_CN.UTF-8

定义 docker-compose 文件
version: ‘3.8’
services:
h1:
build: .
image: centos7-sshd
container_name: h1
privileged: true
command: /usr/sbin/init
hostname: h1.sharkyun.com
networks:
xiuyun_net:
ipv4_address: 172.16.2.10

h2:
build: .
image: centos7-sshd
container_name: h2
privileged: true
hostname: h2.sharkyun.com
command: /usr/sbin/init
networks:
xiuyun_net:
ipv4_address: 172.16.2.20
h3:
build: .
image: centos7-sshd
container_name: h3
hostname: h3.sharkyun.com
privileged: true
command: /usr/sbin/init
networks:
xiuyun_net:
ipv4_address: 172.16.2.30
networks:
xiuyun_net:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.16.2.0/24
gateway: 172.16.2.1

2、构建并启动 docker-compose.yml 中的容器
docker-compose up -d

3、添加一个新的容器进入已有的 compose 项目中
  编辑 compose 文件,并添加新的容器的声明,新的声明放在顶级网络的上面
h4:
build: .
image: centos7-sshd
container_name: h4
hostname: h4.sharkyun.com
privileged: true
command: /usr/sbin/init
networks:
xiuyun_net:
ipv4_address: 172.16.2.40

4、更新 compose 项目
  每次修改完 docker-compose.yml 文件的内容后,只需要重新执行
docker-compose up -d 命令即可立即生效
假如想再加入一个 nginx
version: ‘3.8’
services:
h1:
build: .
image: centos7-sshd
container_name: h1
privileged: true
command: /usr/sbin/init
hostname: h1.sharkyun.com
networks:
xiuyun_net:
ipv4_address: 172.16.2.10

h2:
build: .
image: centos7-sshd
container_name: h2
privileged: true
hostname: h2.sharkyun.com
command: /usr/sbin/init
networks:
xiuyun_net:
ipv4_address: 172.16.2.20
h3:
build: .
image: centos7-sshd
container_name: h3
hostname: h3.sharkyun.com
privileged: true
command: /usr/sbin/init
networks:
xiuyun_net:
ipv4_address: 172.16.2.30
h4:
build: .
image: centos7-sshd
container_name: h4
hostname: h4.sharkyun.com
privileged: true
command: /usr/sbin/init
networks:
xiuyun_net:
ipv4_address: 172.16.2.40
web1:
image: nginx
container_name: web1
hostname: web1
networks:
xiuyun_net:
ipv4_address: 172.16.2.80

networks:
xiuyun_net:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.16.2.0/24
gateway: 172.16.2.1

5、使用其中的一个容器访问 nginx 服务
docker-compose exec h1 curl -I web1
  由于自定义了网络,容器之间可以直接通过服务名或者容器名进行通讯,由于最佳实战就是一个容器对应一个服务,所以是上面的例子服务名称和容器名称是一样的

docker容器原理

一、Docker容器与Docker容器引擎、
1、Docker简介
2、Docker的优势
3、容器三大核心组件
4、Docker的镜像和容器的区别
5、命名空间
6、容器文件系统
7、rootfs和kernel
8、容器的一致性
9、联合文件系统UnionFS/Union File System

二、Docker容器中的数据管理
1、容器的分层结构
2、volume、bind、tmpfs的异同

=======================================================

一、Docker容器与Docker容器引擎
1、Docker简介
  容称是一种虚拟化技术,又称为容器虚拟化技术。容器是基于操作系统的轻量级的虚拟化技术
  容器:将软件打包到一个平台中,用来开发、发布和部署的一种工具,容器可以将软件与周围环境隔离开来,解决开发环境和安装环境之间的差异问题
  容器镜像:一个轻量级、独立、可执行的软件包,包含运行它所需的所有内容(代码、系统工具、系统库、设置)
  Docker只是容器的一种,它将容器发扬光大,成为了容器的代名词
  容器其实是一种沙盒技术。顾名思义,沙盒就是能够像一个集装箱一样,把你的应用"装"起来的技术。这样,应用与应用之间,就因为有了边界而不至于相互干扰;而被装进集装箱的应用,也可以被方便地搬来搬去,这其实是 PaaS 最理想的状态。(云计算服务类型:基础设施即服务IaaS、平台即服务(PaaS、软件即服务SaaS)
  容器的本质是进程,容器就是未来云计算系统中的进程

Docker系统有两个程序:docker服务端和docker客户端
Docker服务端:是一个服务进程,管理着所有的容器。
Docker客户端:是docker服务端的远程控制器,可以用来控制docker的服务端进程。

2、Docker的优势
交付物标准化
  传统的软件交付物包括:应用程序、依赖软件安装包、配置说明文档、安装文档、上线文档等非标准化组件
  Docker的标准化交付物称为"镜像",它包含了应用程序及其所依赖的运行环境,大大简化了应用交付的模式
一次构建,多次交付
  类似于集装箱的"一次装箱,多次运输",Docker镜像可以做到"一次构建,多次交付"。当涉及到应用程序多副本部署或者应用程序迁移时,更能体现Docker的价值
应用隔离
  集装箱可以有效做到货物之间的隔离,使化学物品和食品可以堆砌在一起运输。Docker可以隔离不同应用程序之间的相互影响,但是比虚拟机开销更小。总之,容器技术部署速度快,开发、测试更敏捷;提高系统利用率,降低资源成本。

3、容器三大核心组件
Docker 镜像 - Docker images
Docker 仓库 - Docker registeries
Docker 容器 - Docker containers
Docker仓库
  用来保存镜像,可以理解为代码控制中的代码仓库。同样的,Docker 仓库也有公有和私有的概念。公有的 Docker 仓库名字是 Docker Hub。Docker Hub 提供了庞大的镜像集合供使用。这些镜像可以是自己创建,或者在别人的镜像基础上创建。Docker 仓库是 Docker 的分发部分。
库:registry 英 [ˈredʒɪstri] 美 [ˈredʒɪstri] n.登记处;注册处
公有库:Docker-hub Daocloud ali 网易蜂巢
私有库:公司内部使用(自己部署)
分类:操作系统名称 centos ubuntu
应用名称: nginx tomcat mysql
Tag:表示镜像版本
Docker 镜像
  Docker 镜像是 Docker 容器运行时的只读模板,每一个镜像由一系列的层 (layers) 组成。每一个镜像都可能依赖于由一个或多个下层的组成的另一个镜像。下层那个镜像是上层镜像的父镜像。
镜像名称:仓库名称+镜像分类+tag名称(镜像版本)
完整镜像名称:
docker.io/nginx:v1
docker.io/nginx:latest
daocloud.io/centos:6
镜像ID:64位的id号
基础镜像:一个没有任何父镜像的镜像,谓之基础镜像
Registry中镜像是通过Repository(英 [rɪˈpɒzətri] 美 [rɪˈpɑːzətɔːri] 仓库;资源库;版本库;知识库)来组织的,而每个Repository又包含了若干个Image。Registry包含一个或多个Repository,Image用GUID表示,有一个或多个Tag与之关联

image → repository → registry
镜像 → 版本库 → 仓库
ˈredʒɪstri
rɪˈpɑːzətɔːri

Docker 容器
  Docker 容器和文件夹很类似,一个Docker容器包含了所有的某个应用运行所需要的环境。每一个 Docker 容器都是从 Docker 镜像创建的。Docker 容器可以运行、开始、停止、移动和删除。每一个 Docker 容器都是独立和安全的应用平台,Docker 容器是 Docker 的运行部分

4、Docker的镜像和容器的区别
Docker镜像
  假设Linux内核是第0层,那么无论怎么运行Docker,它都是运行于内核层之上的。这个Docker镜像,是一个只读的镜像,位于第1层,它不能被修改或不能保存状态。一个Docker镜像可以构建于另一个Docker镜像之上,这种层叠关系可以是多层的。第1层的镜像层我们称之为基础镜像(Base Image),其他层的镜像(除了最顶层)我们称之为父层镜像(Parent Image)。这些镜像继承了他们的父层镜像的所有属性和设置,并在Dockerfile中添加了自己的配置
Docker容器
  它会在所有的镜像层之上增加一个可写层。这个可写层有运行在CPU上的进程,而且有两个不同的状态:运行态(Running)和退出态 (Exited)。这就是Docker容器。当我们使用docker run启动容器,Docker容器就进入运行态,当我们停止Docker容器时,它就进入退出态。当我们有一个正在运行的Docker容器时,从运行态到停止态,我们对它所做的一切变更都会永久地写到容器的文件系统中。要切记,对容器的变更是写入到容器的文件系统的,而不是写入到Docker镜像中的。我们可以用同一个镜像启动多个Docker容器,这些容器启动后都是活动的,彼此还是相互隔离的。我们对其中一个容器所做的变更只会局限于那个容器本身。如果对容器的底层镜像进行修改,那么当前正在运行的容器是不受影响的,不会发生自动更新现象。64字符的十六进制的字符串来定义容器ID,它是容器的唯一标识符。容器之间的交互是依靠容器ID识别的,由于容器ID的字符太长,我们通常只需键入容器ID的前4个字符即可。当然,我们还可以使用容器名

5、命名空间
namespace 空间隔离
cgroup   资源限制
rootfs 文件系统
  命名空间空间是 Linux 内核一个强大的特性。每个容器都有自己单独的名字空间,运行在其中的应用都像是在独立的操作系统中运行一样。名字空间保证了容器之间彼此互不影响
pid 命名空间
  不同用户的进程就是通过 pid 命名空间隔离开的,且不同命名空间中可以有相同 pid
net 命名空间
  有了pid命名空间, 每个命名空间中的 pid 能够相互隔离,但是网络端口还是共享 host 的端口。网络隔离是通过 net 命名空间实现的,每个 net 命名空间有独立的网络设备, IP 地址, 路由表, /proc/net 目录。这样每个容器的网络就能隔离开来
mnt命名空间
  类似 chroot,将一个进程放到一个特定的目录执行。mnt 命名空间允许不同命名空间的进程看到的文件结构不同,这样每个命名空间中的进程所看到的文件目录就被隔离开了
uts 命名空间
  UTS(“UNIX Time-sharing System”) 命名空间允许每个容器拥有独立的 hostname 和 domain name, 使其在网络上可以被视作一个独立的节点而非主机上的一个进程
user 命名空间
  每个容器可以有不同的用户和组 id, 也就是说可以在容器内用容器内部的用户执行程序而非主机上的用户

6、容器文件系统
  PaaS 是指平台即服务。 把服务器平台作为一种服务提供的商业模式
  Namespace 的作用是"隔离",它让应用进程只能看到该 Namespace 内的"世界";而 Cgroups 的作用是"限制",它给这个"世界"围上了一圈看不见的墙。这么一折腾,进程就真的被"装"在了一个与世隔绝的房间里,而这些房间就是 PaaS 项目赖以生存的应用"沙盒"。可是,还有一个问题:这个房间四周虽然有了墙,但是如果容器进程低头一看地面,又是怎样一副景象呢?
换句话说,容器里的进程看到的文件系统又是什么样子的呢
  容器里的应用进程,理应看到一份完全独立的文件系统。这样,它就可以在自己的容器目录(比如 /tmp)下进行操作,而完全不会受宿主机以及其他容器的影响。
  事实上:即使开启了 Mount Namespace,容器进程看到的文件系统也跟宿主机完全一样
  Mount Namespace 跟其他 Namespace 的使用略有不同的地方:它对容器进程视图的改变,一定是伴随着挂载操作(mount)才能生效。
  我们希望的是:每当创建一个新容器时,我希望容器进程看到的文件系统就是一个独立的隔离环境,而不是继承自宿主机的文件系统。怎么才能做到这一点呢?可以在容器进程启动之前重新挂载它的整个根目录"/"。而由于 Mount Namespace 的存在,这个挂载对宿主机不可见,所以容器进程就可以在里面随便折腾了。
  在 Linux 操作系统里,有一个名为 chroot 的命令可以帮助你在 shell 中方便地完成这个工作。顾名思义,它的作用就是帮你"change root file system",即改变进程的根目录到你指定的位置
  而进入容器之后执行的 /bin/bash,就是 /bin 目录下的可执行文件,与宿主机的 /bin/bash 完全不同。
所以,对 Docker 项目来说,它最核心的原理实际上就是为待创建的用户进程:
1.启用 Linux Namespace 配置;
2.设置指定的 Cgroups 参数;
3.切换进程的根目录(Change Root)。
这样,一个完整的容器就诞生了。不过,Docker 项目在最后一步的切换上会优先使用 pivot_root 系统调用,如果系统不支持,才会使用 chroot。这两个系统调用功能类似

7、rootfs和kernel
  rootfs 只是一个操作系统所包含的文件、配置和目录,并不包括操作系统内核,同一台机器上的所有容器,都共享宿主机操作系统的内核。如果你的应用程序需要配置内核参数、加载额外的内核模块,以及跟内核进行直接的交互,你就需要注意了:这些操作和依赖的对象,都是宿主机操作系统的内核,它对于该机器上的所有容器来说是一个"全局变量",牵一发而动全身。在 Linux 操作系统中,这两部分是分开存放的,操作系统只有在开机启动时才会加载指定版本的内核镜像。这是容器相比于虚拟机的缺陷之一:虚拟机不仅有模拟出来的硬件机器充当沙盒,而且每个沙盒里还运行着一个完整的 Guest OS 给应用随便用。

8、容器的一致性
  由于云端与本地服务器环境不同,应用的打包过程,一直是使用 PaaS 时最"痛苦"的一个步骤。
  但有了容器镜像(即 rootfs)之后,这个问题被解决了。
  由于 rootfs 里打包的不只是应用,而是整个操作系统的文件和目录,也就意味着,应用以及它运行所需要的所有依赖,都被封装在了一起。对于大多数开发者而言,他们对应用依赖的理解,一直局限在编程语言层面。比如Golang Godeps.json。但实际上,一个一直以来很容易被忽视的事实是,对一个应用来说,操作系统本身才是它运行所需要的最完整的"依赖库"。

9、联合文件系统UnionFS/Union File System
docker公司将rootfs引入层的概念(增量rootfs)创新为union
  联合文件系统:Union File System 也叫 UnionFS
Docker 公司在实现 Docker 镜像时并没有沿用以前制作 rootfs 的标准流程,做了一个创新:Docker 在镜像的设计中,引入了层(layer)的概念。也就是说,用户制作镜像的每一步操作,都会生成一个层,也就是一个增量 rootfs。用到了一种叫作联合文件系统(Union File System)的能力。
  主要的功能是将多个不同位置的目录联合挂载(union mount)到同一个目录下
利用Linux7自带的联合文件系统理解Union

在这个合并后的目录 C 里,有 a、b、x 三个文件,并且 x 文件只有一份。这,就是"合并"的含义。此外,如果在目录 C 里对 a、b、x 文件做修改,这些修改也会在对应的目录 A、B 中生效

二、Docker容器中的数据管理
1、容器的分层结构
layer 英 [ˈleɪə®] 美 [ler]
n.层;表层;层次;阶层
v.把…分层堆放
Container Layer容器可写层
lmage Layer镜像只读层

默认情况下,容器内创建的所有文件都存储在可写容器层上
  这意味着:
  1、当容器不再运行时,数据不会持续存在,并且如果另一个进程需要数据,则很难从容器中获取数据。
  2、容器的可写层紧密耦合到容器运行的主机。您无法轻松地将数据移到其他地方。
  3、写入容器的可写层需要存储驱动程序来管理文件系统。存储驱动程序使用Linux内核提供联合文件系统。与使用直接写入主机文件系统的数据卷相比,这种额外的抽象性能会降低性能 。
  Docker 容器有卷和绑定挂载两种方式可将容器中的文件存储在宿主机的文件系统上,这样即使在容器停止之后这些文件也会被保留。如果你在Linux上运行Docker,你也可以使用tmpfs 挂载。

2、volume、bind、tmpfs的异同

a. 相同之处
  无论您选择使用哪种类型去使用,数据在容器内看起来都是相同的。它被视为容器文件系统中的目录或单个文件
b. 不同之处
  1、

容器进阶

一、Docker资源限制
1、系统压力测试工具
2、限制CPU Share
3、限制容器能够使用的CPU核数
4、内存资源
5、IO资源

二、容器端口转发
三、部署私有仓库
四、固定容器IP
五、BUG整理
1、基于Centos7的容器出现的一个BUG
2、解决容器内字符集乱码的问题

============================================================

一、Docker资源限制
1、系统压力测试工具
stress
  是一个linux下的压力测试工具,专门为那些想要测试自己的系统,完全高负荷和监督这些设备运行的用户
yum -y install stress
测试场景举例
测试CPU负荷
stress –c 4
增加4个cpu进程,处理sqrt()函数函数,以提高系统CPU负荷

内存测试
stress –i 4 --vm 10 --vm-bytes 1G --vm-hang 100 --timeout 100s
新增4个io进程,10个内存分配进程,每次分配大小1G,分配后不释放,测试100S

磁盘I/O测试
stress –d 1 --hdd-bytes 3G
新增1个写进程,每次写3G文件块

硬盘测试(不删除)
stress -i 1 -d 10 --hdd-bytes 3G –hdd-noclean
新增1个IO进程,10个写进程,每次写入3G文件块,且不清除,会逐步将硬盘耗尽。

stress各主用参数说明(-表示后接一个中划线,–表示后接2个中划线,均可用于stress后接参数,不同表达方式)
–help 显示帮助信息
–version 显示软件版本信息
-t secs:
–timeout secs指定运行多少秒
-c forks:
–cpu forks 产生多个处理sqrt()函数的CPU进程
-m forks
–vm forks:产生多个处理malloc()内存分配函数的进程,后接进程数量
-i forks
–io forks:产生多个处理sync()函数的磁盘I/O进程
–vm-bytes bytes:指定内存的byte数,默认值是1
–vm-hang:表示malloc分配的内存多少时间后在free()释放掉
-d :
–hdd:写进程,写入固定大小,通过mkstemp()函数写入当前目录
–hdd-bytes bytes:指定写的byte数,默认1G
–hdd-noclean:不要将写入随机ascii数据的文件unlink,则写入的文件不删除,会保留在硬盘空间。

2、限制CPU Share
CPU 资源
  主机上的进程会通过时间分片机制使用 CPU,CPU 的量化单位是频率,也就是每秒钟能执行的运算次数。为容器限制 CPU 资源并不能改变 CPU 的运行频率,而是改变每个容器能使用的 CPU 时间片。理想状态下,CPU 应该一直处于运算状态(并且进程需要的计算量不会超过 CPU 的处理能力)。
docker 限制 CPU Share
什么是cpu share:
  docker 允许用户为每个容器设置一个数字,代表容器的 CPU share,默认情况下每个容器的 share 是 1024。这个 share 是相对的,本身并不能代表任何确定的意义。当主机上有多个容器运行时,每个容器占用的 CPU 时间比例为它的 share 在总额中的比例。docker 会根据主机上运行的容器和进程动态调整每个容器使用 CPU 的时间比例。
例子:
  如果主机上有两个一直使用 CPU 的容器(为了简化理解,不考虑主机上其他进程),其 CPU share 都是 1024,那么两个容器 CPU 使用率都是 50%;如果把其中一个容器的 share 设置为 512,那么两者 CPU 的使用率分别为 67% 和 33%;如果删除 share 为 1024 的容器,剩下来容器的 CPU 使用率将会是 100%。
好处:
能保证 CPU 尽可能处于运行状态,充分利用 CPU 资源,而且保证所有容器的相对公平;
缺点:
无法指定容器使用 CPU 的确定值。
设置 CPU share 的参数:
-c --cpu-shares,它的值是一个整数。

3、限制容器能使用的CPU核数
  -c --cpu-shares 参数只能限制容器使用 CPU 的比例,或者说优先级,无法确定地限制容器使用 CPU 的具体核数;从 1.13 版本之后,docker 提供了 --cpus 参数可以限定容器能使用的 CPU 核数。这个功能可以让我们更精确地设置容器 CPU 使用量,是一种更容易理解也因此更常用的手段。
  --cpus 后面跟着一个浮点数,代表容器最多使用的核数,可以精确到小数点二位,也就是说容器最小可以使用 0.01 核 CPU
  如果多个容器都设置了 --cpus ,并且它们之和超过主机的 CPU 核数,并不会导致容器失败或者退出,这些容器之间会竞争使用 CPU,具体分配的 CPU 数量取决于主机运行情况和容器的 CPU share 值。也就是说 --cpus 只能保证在 CPU 资源充足的情况下容器最多能使用的 CPU 数,docker 并不能保证在任何情况下容器都能使用这么多的 CPU(因为这根本是不可能的)如果设置的 --cpus 值大于主机的 CPU 核数,docker 会直接报错

4、内存资源
  默认情况下,docker 并没有对容器内存进行限制,也就是说容器可以使用主机提供的所有内存。这当然是非常危险的事情,如果某个容器运行了恶意的内存消耗软件,或者代码有内存泄露,很可能会导致主机内存耗尽,因此导致服务不可用。对于这种情况,docker 会设置 docker daemon 的 OOM(out of memory) 值,使其在内存不足的时候被杀死的优先级降低。另外,就是你可以为每个容器设置内存使用的上限,一旦超过这个上限,容器会被杀死,而不是耗尽主机的内存。
  限制内存上限虽然能保护主机,但是也可能会伤害到容器里的服务。如果为服务设置的内存上限太小,会导致服务还在正常工作的时候就被 OOM 杀死;如果设置的过大,会因为调度器算法浪费内存。因此,合理的做法包括:为应用做内存压力测试,理解正常业务需求下使用的内存情况,然后才能进入生产环境使用,一定要限制容器的内存使用上限,尽量保证主机的资源充足,一旦通过监控发现资源不足,就进行扩容或者对容器进行迁移,如果可以(内存资源充足的情况),尽量不要使用 swap,swap 的使用会导致内存计算复杂,对调度器非常不友好
Docker 限制容器内存使用量
  在 docker 启动参数中,和内存限制有关的包括(参数的值一般是内存大小,也就是一个正数,后面跟着内存单位 b、k、m、g,分别对应 bytes、KB、MB、和 GB):
-m --memory:容器能使用的最大内存大小,最小值为 4m
–memory-swap:容器能够使用的 swap 大小
–kernel-memory:容器能够使用的 kernel memory (内核内存)大小,最小值为 4m
Docker 限制容器内存使用计算
关于 --memory-swap 的设置: --memory-swap 必须在 --memory 也配置的情况下才能有用。

如果 --memory-swap 的值大于 --memory,那么容器能使用的总内存(内存 + swap)为 --memory-swap 的值,能使用的 swap 值为 --memory-swap 减去 --memory 的值

如果 --memory-swap 为 0,或者和 --memory 的值相同,那么容器能使用两倍于内存的 swap 大小,如果 --memory 对应的值是 200M,那么容器可以使用 400M swap

如果 --memory-swap 的值为 -1,那么不限制 swap 的使用,也就是说主机有多少 swap,容器都可以使用

5、IO资源
  对于磁盘来说,考量的参数是容量和读写速度,因此对容器的磁盘限制也应该从这两个维度出发。目前 docker 支持对磁盘的读写速度进行限制,但是并没有方法能限制容器能使用的磁盘容量(一旦磁盘 mount 到容器里,容器就能够使用磁盘的所有容量)。限制磁盘的读写速率,docker 允许你直接限制磁盘的读写速率,对应的参数有:

限制磁盘读写速率
–device-read-bps:磁盘每秒最多可以读多少比特(bytes)
–device-write-bps:磁盘每秒最多可以写多少比特(bytes)
  上面两个参数的值都是磁盘以及对应的速率,限制 limit 为正整数,单位可以是 kb、mb 和 gb。

限制磁盘读写频率(每秒能执行多少次读写操作):
–device-read-iops:磁盘每秒最多可以执行多少 IO 读操作
–device-write-iops:磁盘每秒最多可以执行多少 IO 写操作
上面两个参数的值都是磁盘以及对应的 IO 上限

二、容器端口转发
使用端口转发解决容器端口访问问题
-p 真机端口:容器端口
创建应用容器的时候一般会做端口映射,这样是为了让外部能够访问这些容器里的应用。可以用多个-p指定多个端口映射关系

三、部署私有仓库(没看懂我靠)
1、仓库镜像,Docker hub官方已提供容器镜像registry,用于搭建私有仓库:拉取镜像:docker pull daocloud.io/library/registry:latest
2、运行容器:docker run --restart=always -d -p 5000:5000 daocloud.io/library/registry
3、连接容器查看端口状态:docker exec -it  1f444285bed8  /bin/sh     //这里是sh 不是bash
/ # netstat -antpl //查看5000端口是否开启(容器内查看)
4、在本机查看能否访问该私有仓库, 看看状态码是不是200
curl -I 127.0.0.1:5000
HTTP/1.1 200 OK
Cache-Control: no-cache
Date: Thu, 08 Oct 2020 05:34:32 GMT
5、为了方便,下载1个比较小的镜像,buysbox: docker pull busybox
6、上传前必须给镜像打tag 注明ip和端口。docker tag busybox  本机IP:端口/busybox
tag后面可以使用镜像名称也可以使用id,我这里使用的镜像名称,如果使用官方的镜像,不需要加前缀,但是daocloud.io的得加前缀
7、修改请求方式为http
默认为https,不改会报以下错误:
Get https://master.up.com:5000/v1/_ping: http: server gave HTTP response to HTTPS client
[root@xingdian ~]# vim /etc/docker/daemon.json
{ “insecure-registries”:[“192.168.245.136:5000”] }
重启docker:
systemctl restart docker
8、上传镜像到私有仓库:docker push 192.168.245.136:5000/busybox
9、查看私有仓库里的所有镜像:curl 192.168.245.130:5000/v2/_catalog
{“repositories”:[“busybox”]}

四、固定容器IP
docker安装后,默认会创建三种类型的网络类型,bridge、host、none

显示当前网络:
docker network list
docker network ls
NETWORK ID NAME DRIVER SCOPE
a18d1812f83c bridge bridge local
6e3fd5cdecb2 host host local
76358a258139 none null local

docker外查看容器ip:
docker inspect 容器名称/ID
最后面跟的网络里面,有ip信息

bridge:网络桥接
  默认情况下启动、创建容器都是用该模式,所以每次docker容器构建时会按照顺序获取对应ip地址,这就导致容器每次构建,ip都发生变化
none:无指定网络
  启动容器时,可以通过–network=none,docker容器不会分配局域网ip
host:主机网络
  docker容器的网络会附属在主机上,两者是互通的

创建固定IP容器
1、创建自定义网络类型,并且制定网段
docker network create --subnet=192.168.0.0/16 staticnet
删除自定义的网络 docker network rm staticnet
查看自定义网络 docker network ls

2、使用新的网络类型创建并启动容器
docker run -it --network staticnet --ip 192.168.0.2 centos:7 /bin/bash
docker inspect 容器名称/ID 查看docker ip
user specified IP address is supported on user defined networks only
–ip参:用户指定的IP地址仅在用户定义的网络上受支持
–network不指定–ip就会按照顺序分配ip

五、BUG整理
1、基于Centos7的容器出现的一个BUG
centos7下部署的docker容器中启动服务,报错如下:
[root@a3c8baf6961e .ssh]# systemctl restart sshd.service
Failed to get D-Bus connection: Operation not permitted

这是centos7容器里面出现的一个BUG!
即centos7镜像创建的容器里面安装服务后,不能用systemctl/service启动服务,centos6的容器里没有这个坑!可以通过使用其他的方式启动或者换用centos6的镜像来避免这个错误。
解决方案如下:
原因是dbus-daemon没能启动。其实systemctl并不是不可以使用,可以将你的CMD设置为/usr/sbin/init即可。这样就会自动将dbus等服务启动起来。即采用 /usr/sbin/init自动启动dbus daemon;即把之前的容器关闭并删除(docker stop container-id),然后重新启动容器,注意:启动时一定要加上参数–privileged和/usr/sbin/init,如下:
docker run --privileged -it centos7:7.3.1611 /sbin/init
查看容器这里注意,宿主机可能会出现注销当前登陆账户的情况。

2、解决容器内字符集乱码的问题
容器内操作:
修改.vimrc文件,添加三行设置字体
通常有2个地方保存这个文件的:
(1) 在/etc/文件夹下面,是所有用户的vim配置
(2)每个用户的开始登录的文件夹下面,有些不一定有,比如hadoop用户,则在/home/hadoop下面。
set fileencodings=utf-8,gb2312,gb18030,gbk,ucs-bom,cp936,latin1
set enc=utf8
set fencs=utf8,gbk,gb2312,gb18030

Docker#Docker前一阶段的复习相关推荐

  1. 基于docker部署前后端分离项目--->docker+Dockerfile+vue+nginx+uwsgi+django+socket+负载均衡

    1. 介绍 本文基于阿里云服务器,安装的ubuntu20.04系统 适用于conten7.5系列 适用于ubuntu16.04以上系列 vue已经打包完成,所以不能使用我的vue项目 2. 部署 部署 ...

  2. Docker | Docker技术基础梳理(五) - Docker网络管理

    Docker | Docker技术基础梳理(五) - Docker网络管理 链接: 原文链接 原文链接: https://gitbook.cn/books/5b8f3c471966b44b00d265 ...

  3. Docker - Docker Container及Container命令详解

    Docker - Docker Container及Container命令详解 什么是Docker容器(Docker Container) 上一篇博客介绍了Docker镜像(Docker Image) ...

  4. 【Docker三连问】什么是Docker? | Docker风靡原因? | 如何安装使用Docker?

    参考链接 官网:Home - Docker 文档:Docker Documentation | Docker Documentation 接下来让我们带着对[Docker]的三连问--What.Why ...

  5. Docker#Docker的基本使用

    cherrytree版本 一.docker的安装和卸载 默认/var/lib/docker/目录下面存放Docker的镜像.容器.卷.网络文件,保证/var/所在容量大于40G Docker容器其实就 ...

  6. Docker——docker存储驱动原理

    摘要 Docker 主要是基于 Namespace.cgroups 和联合文件系统这三大核心技术实现的.联合文件系统(Union File System,Unionfs)是一种分层的轻量级文件系统,它 ...

  7. [转帖]Docker里运行Docker docker in docker(dind)

    Docker里运行Docker docker in docker(dind) http://www.wantchalk.com/c/devops/docker/2017/05/24/docker-in ...

  8. docker mysql 操作_[Docker] Docker 快速搭建本地MySQL开发环境

    [Docker] Docker 快速搭建本地MySQL开发环境 关于 Docker 的安装使用本文不再赘述,有兴趣的可以通过官网或是浏览我的专栏文章了解.今天着重给大家介绍下如何利用Docker快速搭 ...

  9. Docker : Docker 安装ES

    1.美图 2.概述 3.公共 创建网段 Docker : Docker创建自定义网桥 4.安装es 4.1.拉取镜像 (base) lcc@lcc ~$ docker pull docker.elas ...

最新文章

  1. tomcat5.5.9+sql2000数据库连接池配置
  2. ArcBruTile 0.2.2
  3. 史上最快的拼接字串方法
  4. net.sf包JSONArray与JSONObject遍历
  5. 信号量使用例子_用信号量锁定:一个例子
  6. 开发小Tips-setValue
  7. unity全栈开发是什么意思_unity游戏公司面试问题总结
  8. linux6同步时间,centos 6.x 同步网络时间
  9. 《Deep Learning》—— 数学基础
  10. 电脑任务栏跑到右边去了_手把手教你用U盘安装Win10系统?学会了再也不用去跑电脑店了...
  11. C++ MFC字体设置
  12. HAV-down1.1vs 大黄峰资源搜索 绿色特别版
  13. JS生成UUID唯一标识方法
  14. flask爱家租房项目开发(一)
  15. [导入]把域名转到了GoDaddy下
  16. 西安电子科技大学c语言答案,西安电子科技大学2021春 面向对象程序设计(C++)大作业答案...
  17. Kubernetes Pod垂直自动伸缩(VPA)
  18. Python——列表推导式
  19. 编程练习题4.21 ( 检查 SSN ) 编写一个程序, 提示用户输入一个社保号码, 它的格式是 DDD-DD-DDDD, 其中 D 是一个数字。 你的程序应该判断输入是否合法。
  20. AutoCAD2014打开闪退的解决办法

热门文章

  1. 小doge的快乐阳光跑 //最短路+dp
  2. 2021-04-20 #CentOS7.4普通用户编写脚本利用lftp进行sftp数据传输
  3. html+css设计两个摆动的大灯笼
  4. 手机手动设置代理之后打不开页面
  5. 【Vue】问题:解决苹果手机点击输入框页面自动放大问题
  6. 机械键盘中的六键无冲突和全键无冲突
  7. 小蔡电脑助手3.0新版全新发布上线
  8. 【BUG】url 参数 AES 加密和解密问题
  9. Jenkin安装和部署
  10. 网友:Photoshop太贵,用不起,Adobe:拿去用,不要钱