Docker容器-从最基础到Dockerfile、Docker-compose,有这一篇足够了!!!

Docker容器

容器背景

  1. 随着云计算和DevOps生态圈的蓬勃发展,产生了大量优秀的系统和软件。软件开发人员可以自由选择各种软件应用环境。但同时带来的问题就是需要维护一个非常庞大的开发、测试、预上线、和生产环境。面对这种情况,docker容器技术横空出世、提供了简单、灵活、高效的解决方案,不需要改变现有的使用习惯,就可以和已有的工具进行整合。因此,掌握docker相关技术也是途径云计算的必经之路。
  2. Docker是在Linux容器里运行应用的开源容器管理工具,可以理解为轻量级的“虚拟机”。它诞生于 2013 年初,最初是 DotCloud 公司内部商业版项目,后来更换架构师,此架构师将Docker进行了开源,导致Docker使用人员增多。基于 Google公司推出的 Go(Golang) 语言开发。该项目后来加入了Linux基金会,遵从了Apache 2.0协议进行推广,项目代码在 GitHub(https://github.com/docker)上进行维护。
  3. **docker官网:**https://www.docker.com/
  4. Docker的Logo设计为蓝色鲸鱼,拖着许多集装箱。鲸鱼可以看做宿主机,而集装箱可以理解为实现应用相互隔离的容器,每个集装箱中都包含自己的应用程序。正如Docker的设计宗旨一样:Build、Ship and Run Any App、Anywhere,即通过对应用组件的封装、发布、部署、运行等生命周期的管理、达到应用组件级别的“一次封装,到处运行”的目的。这里的组件,既可以是一个应用,也可以是一套服务,甚至是一个完整的操作系统。

一、虚拟化与传统物理机部署方式

1.传统物理机部署:

部署非常慢、成本高、资源浪费、难于迁移和扩展、可能会被限定硬件厂商

2.虚拟化技术:

一个物理机可以部署多个app,每个app独立运行在一个vm里,现如今虚拟主机、web服务器、数据库、对象存储等等各种服务都可以同个各种各样的云平台来完成

3.虚拟化:

是一种资源管理技术,是将计算机的各种实体资源(CPU、内存、磁盘空间、网络适配等),予以抽象、转换后呈现出来并可供分割、组合为一个或多个电脑配置环境

4.镜像和容器的区别

镜像是只读的,就是拉到本地并没有运行

容器是可写的,已经运行并且能进入到容器内

docker容器与传统虚拟化的对比

特性 容器 虚拟机
启动时间 秒级 分钟级
资源损耗 几乎无 至少损耗50%左右(系统占用)
硬盘空间 MB GB
系统支持 上千个 几十个
隔离性 资源限制 完全隔离
性能 接近原生 弱于

二、docker优点

1.快速的交付和部署:

对(DevOps)人员来说,最希望的就是项目环境一次创建或配置,可以在任意地方正常运行。开发者可以使用一个标准的镜像来构建一套项目开发容器,代码开发完成之后,运维人员可以直接此容器打包迁移。Docker可以快速创建容器,快速迭代应用程序,并让整个过程全程可见,使团队中的其他成员更容易理解应用程序是如何创建和工作的。Docker将会大量地节约开发、测试、部署的时间。

2.高效的虚拟化:

Docker容器的运行不需要额外的管理系统支持,它是内核级的虚拟化,并且容器调用的是宿主机的bin和lib。因此可以实现更高的性能和效率。

3.更轻松的迁移和扩展:

Docker容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个平台。

4.简单的管理:

使用 Docker只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理

三、docker的底层原理:

Docker是基于google公司推出的golang语言开发而来,基于linux系统内核的Cgroups、NmaeSpace,以及Union FS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术

对进程进行封装隔离,属于操作系统层面的虚拟化技术

利用docker可以实现开发,测试,生产环境的部署一致性,极大的减少运维成本

1.docker核心组件:

Image镜像,构建容器(我们讲应用程序所需要的环境,打包为镜像文件)

Container,容器(应用程序跑在容器中)

镜像仓库(dockerhub)保存镜像文件,提供上传,下载镜像,作用好比github

Dockerfile,将你部署项目的操作,写成一个部署脚本,这就是dockerfile,且该脚本还能够构建出镜像文件

2.创建容器过程:

获取镜像,如docker pull centos,从镜像仓库拉取

使用镜像创建容器

分配文件系统,挂载一个读写层,在读写层加载镜像

分配网络/网桥接口,创建一个网络接口,让容器和宿主机通信

容器获取ip地址

执行容器命令,如/bin/bash

反馈容器启动结果

3.概念名称

镜像:image

容器:container

仓库:Repository

四、docker安装部署

1.环境

docker必须在centos7平台,内核版本不低于3.10

uname -r 查看本主机内核

环境初始化 关闭防火墙、安全机制

2.开启linux内核的路由转发(也就是宿主机能干啥容器也能干啥)
cat <<EOF > /etc/sysctl.d/docker.conf

net.bridge.bridge-nf-call-ip6tables = 1

net.bridge.bridge-nf-call-iptables = 1

net.ipv4.conf.default.rp_filter = 0

net.ipv4.conf.all.rp_filter = 0

net.ipv4.ip_forward=1

EOF

加载修改内核的参数配置文件

modprobe br_netfilter

sysctl -p /etc/sysctl.d/docker.conf

3. yum快速安装docker
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

yum -y install yum-utils device-mapper-persistent-data lvm2

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

yum install docker-ce

systemctl start docker
systemctl enable docker

清理缓存创建新的缓存

yum clean all && yum makecache

安装yum -y install docker-ce

卸载yum -y remove docker-版本号

4.配置docker镜像加速器,拉取镜像
mkdir /etc/docker  #如果没有启动docker需要创建此目录
cat > /etc/docker/daemon.json << EOF 
{ 
"registry-mirrors": ["https://8xpkSwnt.mirror.aliyuncs.com"] 
} 
EOF
5.启动使用docker

systemctl daemon-reload ##重新加载配置文件

systemctl start docker ##启动docker

systemctl enable docker ##设为开机自启动

//查看是否设置为开机自启动systemctl is-enabled 服务名称
[root@localhost ~]# systemctl is-enabled docker
enabled
\##查看docker有没有启动成功
ps -ef |grep dockerdocker version

启动/停止docker
//启动
systemctl start docker
//停止
systemctl stop docker
//开机自启
systemctl enable docker
//重启docker
systemctl restart docker
//查看状态
systemctl status docker

五、docker命令及用法

一些快捷键
esc键+.  #可以调用上一条命令
ctrl+insert  #复制
shift+insert #粘贴
ctrl+r #输入某个单词搜索历史命令
ctrl+p #返回上一次输入命令字符

查看版本信息
//docker 帮助命令
docker --help 
//如果忘记某一个命令怎么使用,有哪些参数
eg:docker pull --help

//查看docker内组件及版本信息
docker version
//查看docker版本信息
docker --version
//显示docker的系统信息,包括镜像和容器的数量
docker info
  docker images 或docker image ls
选项:
-q  或 --quit #只显示镜像的id
-qa #显示所有镜像的id
--format #格式化显示镜像 例::docker images --format "{{.ID}}--{{.Repository}}"
##参数详解:
REPOSITORY:镜像的仓库源
TAG:镜像的标签
IMAGE ID:镜像的id
CREATED:镜像的创建时间
SIZE:镜像的大小
//打标签(原有的容器删除,标签还能继续使用)
docker tag 镜像名 自定义标签名
//查看一个镜像具体信息加inspect参数即可
docker image inspect 镜像id
查找镜像&拉取
//查找镜像,查到之后一般选择第一个,是官方认证
docker search nginx ##nginx为镜像名
//拉取镜像,如果不加版本号会自动拉取最新版本,如果本地没有会直接拉取
docker pull nginx:1.22.1
查看容器内详细信息
##查看容器的详细信息,用于高级的调试
docker container inspect 容器id/容器名称
查看容器日志信息
##查看容器内的所有日志信息
docker logs 容器id/容器名称
docker logs -f --tail=要查看末尾多少行 默认all 容器ID
-f   实时刷新

##查看容器端口转发情况
docker port 容器id/容器名称
查看容器进程
##登录方式
docker run -it 自定义起的那个名 bash
##查看容器内进程信息
docker top 容器id
##动态查看容器内资源信息
docker stats 容器id
运行镜像
//运行镜像
docker run -d -p 80:80 nginx
//选项
-d              ##后台运行容器
-p              ##宿主机端口:容器内端口(端口映射)/tcp (tcp指定远程传输协议)  当访问宿主机端口也就是访问到了容器内的端口,启动后会返回一个容器id
--expose:接受指定范围作为参数比如:--expose=2000~3000
-P               ##大P 随机指定端口
-it               ##使用交互方式运行, 进入容器查看内容
--rm             ##运行测试一个容器,当挂掉之后不会有记录自动删除
--name  自己起的名 镜像名  ##给容器起个名字
//查看有哪些容器在运行
docker ps  ##查看启动的容器
//参数详解:
CONTAINER ID     镜像id号
IMAGE           依赖于哪个镜像运行
COMMANE        里面执行的命令
CREATED          创建时间
STATUS           状态
PORTS            端口映射
NAMES           名称
//选项
-a 列出当前正在运行的容器+历史运行过的容器
-n=?显示最近创建的?容器
-q 显示运行容器的编号(id)
-l 只显示最近启动的一个容器
-v 宿主机目录:容器里边的路径 数据持久化

//运行centos发行版,运行容器且进入容器内: 
## -it交换式命令操作 bash进入容器后执行的命令 --restart=always 容器出现问题后一致重启
docker run -itd -p id号 /bin/bash
eg:docker run -itd -p 9000:8080 --name tomcat01 tomcat:8.0.52 /bin/bash
eg:docker run -d --restart=always -p 80:80 -v /opt/data:/tmp/opt/data nginx
##查看是否切换到容器内的发行版本(centos)
cat /etc/redhat-releas
##查看是否切换到容器内的发行版本(ubuntu)
cat /etc/lsb-release    
##查看是否切换到容器内的发行版本(opensuse)suse为花钱的
cat /etc/SuSE-release
打标签(起名字)
//有的时候呢,我们需要对一个镜像进行分类或者版本迭代操作
docker tag 源镜像名 新的镜像名
eg:docker tag nginx nginx01
#源镜像删除,打包的镜像不会被删除,还可以使用
更改容器名
docker rename 容器ID/容器名 新容器名
进入容器内
##进入到正在运行的容器内 #/bin/bash使用的解释器
docker exec -it 镜像id /bin/bash
docker attch 容器名/容器id
#比如默认运行的centos镜像,不提供vim运行该容器后,在容器内安装vim,然后提交该镜像,在导出镜像为压缩文件,可以发给其他人用
docker connit     
#制作新的容器,运行基础的centos,在容器内安装vim然后提交新的运行镜像,退出,然后容器就会挂掉,在运行出的容器,就默认携带vim了
docker commit 安装过vim的容器的id 自定义起个名
-m 说明信息
-a 作者信息
-p 生成过程中停止容器的运行
启动停止容器
//创建容器但不运行
docker create
//停止运行容器
docker stop 镜像id/镜像名
//启动运行容器
docker start 镜像id/镜像名
//重新启动运行容器
docker restart 镜像id/镜像名
//kill杀掉容器,停止运行
docker kill 容器id/容器名
//启动容器时,可加此参数 --restart=always  #表示该容器随docker服务启动而启动,当服务挂掉docker也会尝试去启动
#如果容器已经启动但是没有加此参数,可以修改其启动配置即可
docker update #更新已经在运行的容器命令参数
docker update --restart=always 容器Id 或者 容器名
或
docker container update --restart=always 容器Id 或者 容器名
登录指定的镜像仓库
docker login
镜像导入/导出
#导出镜像的命令 save 保存 /data/nginx.image下起个名 镜像
docker save -o /data/nginx.image/nginx-1.21.5.tar nginx:1.21.5
#导入镜像 docker image load 从本地文件.tar加载镜像
docker image load -i /opt/centos.tar
docker image load < /opt/centos.tar
#容器的导出 
格式:docker export 容器id/名称 > 文件名  #导出
eg: docker export 21f > centos-exp
#容器的导入
docker import
#将文件拷贝到容器内(无论容器是否开启都可以拷贝)

//将本地的镜像上传到镜像仓库,要先登陆到镜像仓库
docker push 选项 本地镜像
#eg:docker push tomcat:8.0.52
文件复制
//将宿主机下的/root/anaconda-ks.cfg拷贝到容器内的/tmp下  相反在容器里边也可以将文件拷贝到宿主机内
docker cp 宿主机文件路径 容器id:/路径
eg:docker cp /root/anaconda-ks.cfg 1708ad171a07:/tmp
删除
//删除容器运行过的记录
docker rm 镜像id
//删除镜像(被删除的镜像不得有依赖的容器记录)但加-f参数可以强制删除
docker rmi 镜像id(完整的或者前三位也可以)/镜像名
docker rm -f 容器id
//删除全部镜像
docker rmi `docker images -aq`
//批量删除容器
docker rm `docker ps -aq`
// -it开启一个交互式的终端 --rm容器退出时删除该容器
docker run -it --rm centos bash

六、docker仓库

仓库是集中存放镜像的地方

仓库可分为公共仓库和私有仓库

公共仓库就是所谓的网上的 大家都可以使用的

私有仓库值得就是自己本地或者公司内部使用的

官方仓库:https://hub.docker.com/

国内仓库:http://dl.dockerpool.com

仓库注册服务器才是存放仓库具体的服务器(Registry),每个服务器上都可以放置多个仓库,而每个仓库下可以放置多个镜像。每个镜像可以运行多个容器,每个容器上可以跑一个应用或应用组。

七、docker资源限制 Cgroup

docker容器技术层通过cgroupcontrol group控制组,实现容器对物理资源使用的限制,限制的资源包括CPU、内存、磁盘三个方面。基本覆盖了常见的资源配额和使用量控制。

Cgroup是 linux内核提供的一种可以限制、记录、隔离进程组所使用的物理资源的机制,被 LXC及Docker 等很多项目用于实现进程的资源控制。

Cgroup是提供将进程进行分组化管理的功能和接口的基础结构,Docker中I/O 或内存的分配控制等具体的资源管理功能都是通过 Coroup.功能来实现的。这些具体的资源管理功能称为 Cgroup子系统,以下是对几大子系统的介绍。

(黑体用的较多,别的作为了解即可)

  • blkio: 限制块设备的输入输出控制。如:磁盘、光盘、USB 等。

  • cpu:限制 CPU资源的访问

  • cpuacct:产生Cgroup 任务的CPU 资源报告。

  • cpuset:限制分配单独的cpu 和内存资源。

  • devices:允许或拒绝对设备的访问。

  • freezer:暂停和恢复Cgroup 任务。

  • memory: 设置每个Cgroup 的内存限制以及产生内存资源报告。

  • net cls:用于标记每个网络包。

  • ns: 命名空间子系统。

  • perf_event:增加了对每 group 的监测跟踪的能力,可以监测属于某个特定的group 的所有线程以及运行在特定cpu上的线程

–cpuset-cpus、–cpuset-mems参数只在多核、多内存节点上的服务器上有效,并且必须又实际的物理配置匹配,否则也无法达到资源控制的目的。

内存限制:

与操作系统类似,容器可使用的内存包括俩部分:物理内存和swap。docker通过下面俩组参数来控制容器内存咋使用量

  • -m 或–memory:设置内存的使用限额,例如1G、2G…
  • –memory-swap:设置内存swap的使用限额

如:docker run -it -m 200M --memory-swap=300M progrium/stress --vm1 --vm-bytes 280M

–vm1:启动一个内存工作线程。

–vm-bytes 280M:每个线程分配280M内存

如果让工作线程分配的内存超过300M,分配的内存超过限额。stress线程报错。容器就会退出

八、docker持久化

8.1.数据持久化介绍

在docker中若要想实现容器数据的持久化,(所谓的持久化即数据不随着container的结束而销毁),需要将数据从宿主机挂载到容器中,目前docker提供了三种不同的方式将数据从宿主机挂载到容器中。

  1. volumes:docker会管理宿主机文件系统的一部分资源,默认位于/var/lib/docker/volumes目录中(最常用的)
//方二:volume创建卷
[root@localhost ~]# docker volume create nginx-data  #创建一个卷
[root@localhost ~]# docker volume ls  #查看卷
[root@localhost ~]# docker run -itd --name=nginx -p 8000:80 -v nginx-data:/usr/share/nginx/html nginx
4a8ba499ab24646c19896aa6862cf0081e2dcbb61f19460650f65c4d2397d71b
[root@localhost ~]# docker volume inspect nginx-data #查看创建卷的具体信息
[
    {
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/nginx-data/_data",
        "Name": "nginx-data",
        "Options": {},
        "Scope": "local"
    }
]
[root@localhost ~]# docker exec -it 4a /bin/bash
root@4a8ba499ab24:/# ls -l /usr/share/nginx/html/
total 8
-rw-r--r-- 1 root root 497 Dec 28  2021 50x.html
-rw-r--r-- 1 root root 615 Dec 28  2021 index.html
//退出,在宿主机下查看
[root@localhost ~]# ls /var/lib/docker/volumes/nginx-data/_data
50x.html  index.html
#浏览器访问 ip:端口号

//可以看到容器里面的俩个默认页面,由此可知volume帮助我们做了类似于一个软链接的功能。在容器内的改动,我们可以在宿主机里感知,而在宿主机里面的改动,容器里边可以感知到
//更改默认页面
[root@localhost ~]# echo 'yys' > /var/lib/docker/volumes/nginx-data/_data/index.html 
#再次使用浏览器访问 ip:端口号

//如果我们手动stop并且remove当前nginx容器,我们会发现容器卷里面的文件还在,并且没有随着容器被删除掉
docker stop 4a
docker rm -f 4a
[root@localhost ~]# ls /var/lib/docker/volumes/nginx-data/_data/
50x.html  index.html
#从而验证数据卷里边的东西是可以持久化的,如果下次还需要创建一个nginx容器,那么直接使用当前数据卷里边的文件就可以
[root@localhost ~]# docker run -d --name nginx-2 -p 9000:80 -v nginx-data:/usr/share/nginx/html nginx
#在使用原来的数据卷启动一个nginx   使用浏览器访问测试 ip:端口号

//清理卷  如果不使用自定义数据倦了,那么可以手动清理掉
docker volume ls #查看数据卷
docker volume rm 卷名称  #删除数据卷(先将容器停掉在删除对应卷)

//注意:
1.数据卷下无文件,显示容器对应目录下的文件
2.数据卷下有文件,显示数据卷原有文件,并将容器对应目录的文件影藏,显示数据卷文件

  1. bind mounts:意为着可以指定存储在宿主机系统的任意位置(一般使用)
//方一:
#注:-v 指定宿主机目录持久化运行在centos里边,创建一个文件然后退出,目前所有的container的数据都存在/var/lib/docker/volumes下边加容器完整id(可以tab出来)的_data下就可以看到创的文件
[root@localhost ~]# docker run -it -v /opt/ centos /bin/bash
[root@5e475d3f5548 /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr
[root@5e475d3f5548 /]# touch /opt/yys
[root@5e475d3f5548 /]# ls -l /opt/
-rw-r--r-- 1 root root 0 Mar  7 06:16 yys
[root@5e475d3f5548 /]# exit
[root@localhost ~]# ls /var/lib/docker/volumes/
d0c8d6e25af4615347cd10c5d55f9b2bb6e2c15b48b9d24c4e291babdb50840c
metadata.db
[root@localhost ~]# ls /var/lib/docker/volumes/d0c8d6e25af4615347cd10c5d55f9b2bb6e2c15b48b9d24c4e291babdb50840c/_data/
yys

//以nginx举例:
#注:创建一个目录并进去, ${PWD}是显示当前路径,映射到容器内nginx的默认页面下/usr/share/nginx/html
[root@localhost ~]# mkdir -p /data/project
[root@localhost ~]# cd /data/project/
[root@localhost project]# mkdir data
[root@localhost project]# pwd
/data/project
[root@localhost project]# ls
data
[root@localhost project]# docker run -d --name nginx-demo -p 8000:80 -v ${PWD}/data:/usr/share/nginx/html nginx
[root@localhost project]# docker exec -it 41b /bin/bash
root@41b40813a2b2:/# ls -l /usr/share/nginx/html/
total 0
#但是这样宿主机的data下边是没有任何东西的,但是我们可以先运行nginx,将nginx的默认页面拷贝到当前目录下,/data目录就没用了,在启动nginx时候指定cp下来的html目录即可,进入到起来的容器内查看会有俩个文件,为了验证可以修改nginx的默认页面,退出容器查看宿主机拷贝内的默认页面也发生改变,这就是持久化.

[root@localhost project]# docker run -d --name nginx-demo -p 8000:80 nginx
af2b94e070602549bc561567aa372d7805757f0d51931e70b1e494950fccee32
[root@localhost project]# docker cp nginx-demo:/usr/share/nginx/html/ ./
[root@localhost project]# ls
html
[root@localhost project]# ls html/
50x.html  index.html
[root@localhost project]# docker run -d --name nginx-ceshi -p 8080:80 -v ${PWD}/html:/usr/share/nginx/html nginx
[root@localhost project]# docker exec -it nginx-ceshi /bin/bash
root@3a67130e2fd9:/# ls /usr/share/nginx/html/
50x.html  index.html
root@3a67130e2fd9:/# echo 'this is yys' > /usr/share/nginx/html/index.html 
root@3a67130e2fd9:/# exit
exit
[root@localhost project]# ls
html
[root@localhost project]# cat html/index.html 
this is yys

  1. tmpfs:挂载存储在宿主机的内存中,而不会写入宿主机的文件系统,(一般都不会使用)

九、docker网络

1.docker目前对单节点的设备提供了将容器端口映射到宿主机和容器互联俩个网络服务

在docker中容器默认无法与外部通信的,需要在启动命令中加入对应的选项才允许容器与外界通信

2.容器互联

容器互联是除了端口映射外另一种可以与容器的通信方式。端口映射的用途是宿主机网络与容器的通信,而容器互联是容器之间通信

当前实现容器互联有俩种方式,一种是把俩个容器放进一个用户自定义的网络中,另一种是使用–link参数(即将删除的功能)

//它会在源和接收容器之间创建一个隧道,接受容器可以看到源容器指定的信息
--link参数格式:--link name:alias 其中name是要链接的容器名称,alias是这个链接的别名,如果启动的容器没有名称使用docker rename重命名容器
eg:docker run -itd --name=link test:text busybox

一个容器可以同时加入多个网络,使用不同地址可以访问不同网络中的容器

//拉取busybox镜像用作实验,此镜像自带一些工具

1.首先创建俩个容器
docker run -itd --name container1 busybox
docker run -itd --name container2 busybox

2.查看默认网络模式有几种
[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
a784dd59a335        bridge              bridge              local
5a186d09d686        host                host                local
e56f2344ceec        none                null                local
//Host模式,使用--net=host指定。
Container模式,使用--net=container:NAME_or_ID指定。
None模式,使用--net=none指定。
Bridge模式,使用--net=bridge指定,默认设置。

3.创建一个独立的容器网络使用bridge驱动(桥接模式),还有overlay和macvlan俩种模式 --subnet和--gateway可以指定子网和网关
#创建名为demo_net 类型为桥接 子网为192.168.0.0/16
docker network create -d bridge --subnet 192.168.0.0/16 demo_net
#删除创建的网络
docker network rm 网络name名称

#我们把container2加入到demon_net中
docker network connect demo_net container2
#查看有没有加进网络中,注意ip地址是自动分配的
docker network inspect demo_net

4.启动第三个容器
docker run --network=demo_net --ip=192.168.3.3 -itd --name=container3 busybox
--network:指定容器要加入哪个创建的网络
--ip:指定容器IP
--name:容器名称
busybox:使用什么镜像启动

5.分别查看三个容器内的网卡,进行对比
docker exec -it container1 ifconfig
docker exec -it container2 ifconfig
docker exec -it container3 ifconfig
#测试ping一下
docker exec -it container2 ping -c 3 192.168.0.2
docker exec -it container2 ping -c 3 192.168.3.3
3.1.网络模式:host

工作模式:如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的network namespace,而是和宿主机共用一个root network namespace,容器不会虚拟出自己的网卡,配置自己的ip等,而是使用宿主机的ip和端口。生产环境注意安全

//使用busybox镜像启动容器网络模式为host
host模式特点:与宿主机使用相同的端口
docker run -itd --net=host --name=host busybox
验证:宿主机ifconfig查看本机ip
docker exec -it host ifconfig  #俩网卡是否一致
3.2.网络模式:container

这个模式可以指定新建的容器和已经存在的一个容器共享一个network namespace,而不是和宿主机共享,新建的容器不会创建自己的网卡,配置自己的ip,而是和一个指定的容器共享一个ip、端口范围等。

使用–net=container:container_name指定

//启动一个容器
docker run -itd --name host1 busybox
//在起一个容器关联上之前那个
docker run -itd --net=container:host1 --name=host2 busybox
--net:指定网络模式
container:host1 #要关联的容器名称
//验证网卡是否一致
docker exec -it host1 ifconfig
docker exec -it host2 ifconfig
3.3.网络模式:none

在这种模式下,docker容器用有自己的network namespace,但是并不为docker容器进行任何网络配置,也就是说,这个docke容器没有网卡、IP、路由等信息。需要我们自己为docker容器添加网卡、配置ip等

使用–net=none指定,不会配置任何网络,(基本不会使用)

//使用busybox镜像启动一个名称为none的容器网络模式为none
docker run -itd --name=none --net=none busybox
//查看 docker exec -it none ifconfig
3.4.网络模式:bridge

bridge模式是Docker默认的网络设置,属于一种NAT网络模式

Docker daemon在启动的时候就会建立一个docker0网桥(通过-b参数可以指定),每个容器使用bridge模式启动时,Docker都会为容器创建一对虚拟网络接口(veth pair)设备,这对接口一端在容器的Network Namespace,另一端在docker0,这样就实现了容器与宿主机之间的通信。 iptables -nvl -t nat

docker网络映射机制都是基于iptables实现

4.1.网络层中的四层代理七层代理
  1. 四层代理主要工作于OSI模型中的传输层,传输层主要处理消息的传递,而不管消息的内容,TCP常见的是四层协议
  2. 七层代理主要工作于OSI模型的应用层,应用层主要用来处理消息的,比如:http便是常见的七层协议。七层负载均衡服务器起到了反向代理的作用,client端要与七层负载均衡设备三次握手建立TCP连接,把要访问的报文信息发送给七层负载均衡。

**区别:**四层代理只进行一次tcp请求,而七层代理进行了俩次tcp请求

七层负载均衡的cpu密集程度比基于包的四层负载均衡更高,他运用缓存的方式来卸载上游服务器较慢的连接,并显著地提高了性能。

十、docker镜像的原理

当我们使用docker pull 拉取一个镜像的时候发现是下载了多行信息,最终又得到了一个完整的镜像文件,一个完整的docker镜像可以创建处docker容器的运行,例如一个centos:7.8.2003镜像文件,我们获取的是centos7这个发行版,这个镜像文件是不包含linux内核的

1.docker镜像的存放位置

ls /var/lib/docker/image/overlay2/imagedb/content/sha256/

该文件作用是记录镜像和容器的配置关系

2.docker images 镜像搜索地址

https://hub.docker. com/_/centos?tab=tags&page=1&ordering-last_updated

所有对容器的修改动作,都只会发生在容器里,只有容器层是可写的其余镜像层都是只读的

文件操作 说明
添加文件 在容器中创建文件时,新文件被添加到容器中
读取文件 在容器中读取某个文件时,docker会从上往下依次在各镜像层中查到文件,一旦找到,立即将其复制到容器层。然后打开并读入内存
修改文件 在容器中修改已存在的文件时,docker会从上往下依次在各镜像层中查找到文件,一旦找到,立即将其复制到容器层,然后修改
删除文件 在容器中删除文件时,docker也是从上往下依次在镜像层中查找此文件,找到后,会在容器中记录下此操作。(只是记录删除操作)

只有当需要修改时复制一份数据。这种特性被称作copy-on-write,可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何操作

这样就解释了我们前面提出的问题:容器层记录对镜像的修改,所有的镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享

3.docker镜像的实际作用

例开发机器想装东西但是又不想搞乱当前机器的环境,该怎么办?

1.下载安装docker工具

2.获取软件的docker镜像(以后想要的各种工具,基本上都能够搜索到合适的镜像去用)下载nginx镜像: docker pull nginx

3.运行nginx镜像,然后就启动了一个容器,这个nginx服务就运行在容器中

4.停止容器,删除该镜像,你的电脑上就好像没有使用过nginx一样,就好比沙箱一样的环境

沙箱:沙箱是一个虚拟系统程序,沙箱提供的环境相对于每一个运行的程序都是独立的,而且不会对现有的系统产生影响

4.dockerfile 镜像

**作用:**用于构建docker镜像,部署一个用于运行你所需的容器环境,相当于一个脚本,通过dockerfile自己的指令,来构建软件依赖,文件内依赖,存储,等等…

定制docker镜像方式

  1. 手动修改内容,然后docker commit提交容器为新的镜像

  2. 基于dockerfile中定义一系列的命令和参数构成的脚本,然后这些命令应用于基础镜像,依次添加层,最终生产一个新的镜像,极大的简化了部署工作

    官方dockerfile实例:https://github.com/CentOS/CentOS-Dockerfiles

dockerfile主要组成部分:

基础镜像信息 FROM centos:tag(版本)

制作镜像操作指令RUM yum -y install openssh-server

容器启动时执行指令CMD [“/bin/bash”] 要做的事

5.dockerfile指令
FROM 这个镜像的妈妈是谁(指定基础镜像)
MAINTAINER 作者信息
RUN 指定参数中定义的命令,构建镜像时需要的命令
RUN yum -y install vim 
ADD 添加宿主机的文件到容器内并自动解压

特性和COPY基本一致,不过多了一些功能:

  1. 源文件是一个url,此时docker引擎会下载该链接,放入目标路径,且权限自动设为600若这不是期望结果,还得增加一层RUN指令进行调整(后加linux命令即可)
  2. 源文件是一个URL,且是一个压缩包,不会自动解压,也得单独用RUN指令解压(一般不要指定url)
  3. 源文件是一个压缩文件,且是gzip,bzip2,xz,ADD指令会自动解压该文件到目标路径
COPY 作用和ADD是一样的

都是拷贝宿主机的文件到容器内,仅拷贝。但是能够保留源文件的元数据,如:权限、访问时间等等

copy指令从宿主机复制文件--目录到新的一层镜像内
eg:  copy yys.py /home
#支持多个文件,以及通配符形式复制,语法要满足Golang的filepath.Match 
eg:  copy yys* /tmp
WORKDIR 相当于cd命令(设置容器内默认工作目录)
用于在dockerfile中,目录的切换,更改工作目录
WORKDIR /opt
VOLUME 存放东西的地方(设置卷,挂载主机目录,将容器内目录映射到宿主机内)
容器在运行时,应该在保证在存储层不写入任何数据,运行在容器内产生的数据,推荐是挂载,写入到宿主机内,进行维护
#将容器的/data文件夹,在容器运行时自动挂载为匿名卷,任何向该目录中写入数据的操作,都不会被容器记录,保证的容器存储层无状态理念
VOLUME /data  
方式:
1)容器数据挂载的方式,通过dockerfile,指定VOLUME目录
2)通过docker run -v 参数,直接设置需要映射挂载的目录
EXPOSE 向容器外部公开的端口号
帮助使用该镜像的人,快速理解该容器的一个端口业务 
docker port 容器id  ##查看容器端口
docker run -p  ##宿主机端口:容器端口
docker run -P  ##随机宿主机端口:容器内端口
CMD 容器启动时要运行的命令,可以有多个,但只有最后一个生效
用法,注意是双引号
CMD [“参数1”,"参数2”]
在指定了entrypoint指令后,用CMD指定具体的参数

docker不是虚拟机,容器就是一个进程,既然是进程,那么程序在启动的时候需要指定些运行参数,这就是CMD指令作用

例如centos镜像默认的CMD是/bin/bash,直接docker run -it centos会直接进入bash解释器也可以启动容器时候,指定参数,docker run -it centos cat /etc/os-releasea

CMD运行she11命令,也会被转化为she11形式
eg:CMD echo SPATH13
会被转化为
CMD ["sh","-c","echo $PATH"]

$容器内运行程序
这里要注意的是,docker不是虚拟机的概念,虚拟机里的程序运行,基本上都是在后台运行,利用systemctl运行,但是容器内没有后台进程的概念,必须在前台运行。
容器就是为了主机进程而存在的,主进程如果退出了,容器也就失去意义,自动退出。例如:
CMD systemctl start nginx #这样的写法是错误的,容器会立即退出
因为systemctl start nginx 是希望以守护进程形式启动nginx,且CMD命令会转化为
CMD [ "sh","-c","ehco $PATH"]
这样的命令主进程是sh解释器,执行完毕后立即结束了。因此容器也就推出了
因此正确的做法应该是CMD ["nginx","-g","daemon off;"]
ENV环境变量

ARG和ENV一样,设置环境变量,区别在于ENV无论实在镜像构建时,还是容器运行时,该变量可以使用。ARG只是用于构建镜像需要设置的变量,容器运行时就消失了

ENV JAVAPATH /usr/local	# 指定JAVAPATH变量的值为/usr/local/
ENV PATH $JAVAPATH/bin  # 利用 $ 引用上面的JAVAPATH
ENTRYPOINT 指定一个容器启动时运行的命令
和RUN指令-样,分为两种格:
exec
shell
作用和CMD-样,都是在指定容器启动程序以及参数。
当指定了ENTRYPOINT之后,CMD指令的语义就有了变化,而是把CMD的内容当作参数传递给ENTRYPOINT指令。
CMD和ENTRYPOINT的区别:
一个dockerfile中可以写多个CMD指令但是只有最后一个执行
ENTRYPOINT不会被运行的command命令覆盖
USER 用于改变环境,用于切换用户

USER root

USER tom

6.dockerfile 指令用法

要求:通过dockerfile,构建nginx镜像,且运行容器后,生成的页面是自己编辑的东西: 创建Dockerfile,文件名必须是这个

实战–构建nginx
//创建一个目录将tar包、Dockerfile、nginx_install.sh放一起
1.创建文件夹 
mkdir nginx_dockerfile
cd nginx_dockerfile
2.编写dockerfile,注意Dockerfile首字母大写
# vim nginx_dockerfile/Dockerfile
FROM centos:7
ADD nginx-1.16.1.tar.gz /usr/local
COPY nginx_install.sh /usr/local
RUN sh /usr/local/nginx_install.sh
EXPOSE 80
3.编写脚本
# vim nginx_install.sh 
#!/bin/bash
yum -y install gcc gcc-c++ make pcre pcre-devel zlib zlib-devel
cd /usr/local/nginx-1.16.1
./configure --prefix=/usr/local/nginx && make && make install

[root@bogon nginx_dockerfile]# pwd
/root/nginx_dockerfile
[root@bogon nginx_dockerfile]# ls
Dockerfile  nginx-1.16.1.tar.gz  nginx_install.sh

#构建dockerfile  去/nginx_dockerfile目录下有Dockerfile文档
docker build -t mycentos:nginx .

//参数选项:
-f    Dockerfile的名称
-t    打标签(起名)

#运行nginx镜像
docker run -itd -p 80:80 --name nginx_1 nginx
//验证:浏览器查找宿主机ip 是否能访问到自己编写的默认页面

##这就是dockerfile即dockerfile指令带来的便捷

十一、docker compose&编排部署

Docker Compose的前生是Fig,它是一个定义及运行多个Docker容器的工具,可以使用YAML文件配置应用程序的服务,然后使用单个命令,可以创建并自动配置中的有服务,docker compose会通过解析容器间的依赖关系,(linx、网络容器、net-from或数据容器、)按先后顺序启动所定义的容器

Compose是Docker的服务编排工具,注意用来构建基于Docker的复杂应用,Compose通过一个配置文件来管理多个Docker容器,非常适合组合使用多个容器进行开发的场景

1.Compose 适用于所有环境: 生产,开发,测试以及C 工作流程。使用compose 基本上是一个三步过程
  • 使用 packerile定义应用程序的环境,以便在任何地方进行复制。
  • 在docker-composeml中定义组成应用程序的服务,以便它们可以在隔离的环境中一起运行。
  • 运行 docker-compose 开始并运行整个应用程序。

docker-compose 是用来做 docker 的多容器控制,有了 docker-compose 你可以把所有繁复的 docker 操

作全都用一条命令自动化完成。从上图可以看到,这位compose 非常开心的把N多个容器抓在一起,根据自己的心情来编排部署。

Docker对于运维或开发者来说,Docker 最大的优点在于它提供了一种全新的发布机制。这种发布机制,指的是我们使用 Docker 像作为统一的软件制品载体,使用 Docker 容器提供独立的软件运行上下文环境,使用 Docker Hub 提供像统一协作,最重要的是该机制使用Dockerfile 定义容器内部行为和容器关键属性来支撑软件运行。

Dockerfle作为整个机制的核心。在 Dockerfile中不但能够定义使用者在容器中需要进行的操作,而且能够定义容器中运行软件需要的配置,于是软件开发和运维终于能够在一个配置文件上达成统一。运维人员使用同一个 Dockerfile能在不同的场合下“重现”与开发环境

2.Compose的优点

先来了解一下我们平时是怎么样使用 docker的!把它进行拆分一下:

  1. docker search 镜像,是不是先查找一个镜像,
  2. dockerrun-itd 镜像名称,然后在运行这个镜像;
  3. 然后如果你要在运行第二个像、第三个镜像…等等,你是不是又要 docker search docker run 运行。

上面“docker run-itd 像名称“这只是最小的动作,如果你要映射硬盘,设置nat 网络或者映射端口等等。就要做更多的 docker 操作,这显然是非常没有效率的,况且如果你要大规模部署,是不是觉得就很麻烦了。

但是我们写在 docker-compose 里面就很好了。你只需要写好后只运行一句:docker-compose up -d

3.编排和部署

编排,即orchestration,它根据被部署的对象之间的耦合关系,以及被部署对象环境的依赖,制定部署流程中各个动作的执行顺序,部署过程所需要的依赖文件的存储位置和获取方式,以及如何验证部署成功。这些信息都会在编排工具中以指定的格式(比如配置文件或者特定的代码)来要求运维人员定义并保存起来,从而保证这个流程能够随时在全新的环境中可靠有序地重现出来。

部署,即deployment,它是指按照编排所指定的内容和流程,在目标机器上执行编排指定环境初始化,存放指定的依赖和文件,运行指定的部署动作,最终按照编排中的规则来确认联署成功

这么来解释吧,编排是一个指挥家,他的大脑里存储了整个乐曲的演奏流程,对于每一个小节每一段音乐的演奏方式、开始、结束他都了然于胸;部署就是整个乐队,他们严格按照指挥家的意图用乐器来完成乐谱的执行,在需要时开始演奏,又在适当的时机停止演奏。最终,两者通过协作就能把每一位演奏者独立的演奏通过组合、重叠、街接来形成高品位的交响乐。

4.Compose原理

首先,用户执行的 docker-compose up -d 指令调用了命令行中的启动方法。功能很简单明了,一个 docke-compose xml 定义了一个 docker-compose 的 project,docker-compose 操作提供的命令行参数则作为这个 project 的启动参数交由 project 模块去处理。

其次,如果当前宿主机已经存在与该应用对应的容器,docker-compose 将进行行为逻辑判断。如果用户指定可以重新启动已有服务,docker-compose 就会执行 service 模块的容器重启方法,否则就将直接启动已有容器。这两种操作的区别在于前者会停止旧的容器,创建启动新的容器,并把旧容器移除掉。在这个过程中创建容器的各项定义参数都是从docker-compose up 指令和 docker-compose xml中传入的。

接下来,启动容器的方法也很简洁,这个方法中完成了一个 Docker 容器启动所需的主要参数的封装,并在container 模块执行启动。该方法所支持的参数我想大多数朋友过是有所了解的。

最后,container 模块会调用 docker-py客户端执行向 Docker daemon 发起创建容器的POST 请求,再往后就是Docker 处理的范了,相信看过我这篇文章 Docker: 架构拆解请的朋友就明白了。

5.安装docker-compose
[root@localhost ~]# yum -y install docker-compose
6.用法

docker-gompase [-f …] [options] [COMMAND] [ARGS…]

docker-compose 常用选项:

  • -verbose 输出更多调试信息。
  • -version 打印版本并退出。
  • -f,–file FE使用特定的 compose 模板文件,默认为 docker-compase.yml。
  • -P,–project-name NAME 指定项目名称,默认使用目录名称。
7.常用命令

build 构建或重建服务

kill 杀掉容器

logs 显示容器的输出内容

ps 显示容器

pull 拉取镜像

restart 重启服务

rm 删除停止的容器

run 运行一个一次性的容器

scale 设置服务的容器数目

exec 切换到容器内

start 开启服务

stop 停止服务

up 创建并启动容器

其实这些常用命令用 docker 的命令功能是一样的。

8.YAML简介

YAML 是-种标记语言,可读性很强。类似于 XML 数据述语言,语法比 XML 简单的多。YAML 数据结构通过缩进来表示,连续的项目通过减号来表示,键值对用冒号分割,数组用括号括起来,hash 用花括号括起来。

YAML 文件格式注意事项:

在缩排中空白字符的数目并不是非常重要,只要相同阶层的元素左侧对齐就可以了(不过不能使用 TAB 字符);

  • 通常开头缩进 2个空格;
  • 字符的后面缩进 1个空格,比如冒号、逗号、横杆;
  • 支持#注释;
  • 允许在文件中加入选择性的空行,以增加可读性;
  1. docker-compse是面向单宿主机部署的,这是一种部署能力的欠缺。在更多的场合下,管理员需要面对大量物理服务器(或者虚拟机),这时如果要实现基于 docker-compose的容器自动化编排与部署,管理员就得借助成熟的自动化运维工具 (ansible、puppetchefsaltstack)来负责管理多个目标主机,将docker-compose 所需的所有资源(配置文件、用户代码)交给目标主机,然后在目标主机上执行docker-compose 指令。

  2. 同样网络和存储也比较棘手,Docker不能提供跨宿主机的网络,完全面向Dockerdaemon的 dockercompose 当然也不支持。这意味着管理员必须部署一套类似于 open vSwich的独立网络工具,而且管理员还需要完成集成工作。当好不容易把容器编排都安排妥当之后,又会发现容器还处在内网环境中,于是负载均衡、服务发现等一堆问题就面临而来了,这些问题很快能消耗掉工程师所有的耐心。

十二、Docker Harbor

1.什么是Docker Harbor?

Docker Harbor有可视化的Web管理界面可以方便管理Docker镜像操作也方便简单,又提供了多个项目的镜像权限管理控制功能等。

Harbor是VMware公司开源的企业级Docker Registry项目,其目标是帮助用户迅速搭建一个企业级的Docker Registry仓库服务。它以Docker公司开源的Registry为基础,提供了管理UI。基于角色的访问控制(Role Based AccessControl)、AD/LDAP集成、以及审计日志 (Auditlogging) 等企业用户需求的功能。通过添加一些企业必需的功能特性,例如安全、标识和管理等,扩展了开源Docker Distribution。作为一个企业级私有Registry服务器,Harbor提供了更好的性能和安全,以提升用户使用 Registry 构建和运行环境传输镜像的效率。

2.Harbor的优势:
  1. 基于角色控制:用户和仓库都是基于项目进行组织的,而用户基于项目可以拥有不同的权限。
  2. 基于镜像的复制策略: 镜像可以在多个 Harbor 实例之间进行复制(同步)。适用于负载平衡、高可用性、多数据中心、混合和多云场景。
  3. 支持 LDAP / AD:Harbor 与现有的企业 LDAP / ADA 集成,用于用户认证和管理。
  4. 图像删除和垃圾收集:镜像可以被删除,也可以回收镜像占用的空间。
  5. 图形 UI:用户可以轻松浏览、搜索镜像仓库以及对项目进行管理。
  6. 审计: 对存储库的所有操作都进行记录。
  7. RESTful API:用于大多数管理操作的 RESTful API,易于与外部系统集成。
3.Harbor架构构成
  1. Proxy:Harbor 的 Registry、UI、token 等服务。通过一个前置的反向代理统一接收浏览器Docker 客户端的请求,并将请求转发给后端不同的服务。
  2. Registry:负责储存Docker镜像,并处理 Docker push/pull 命令。由于要对用户进行访问控制,即不同用户对Docker image有不同的读写权限,Registry会指向一个 token服务,强制用户的每次 Docker pull/push 请求都要携带一个合法的token,Registry会通过公钥对 token 进行解密验证。
  3. Core services 这是 Harbor 的核心功能,主要提供以下服务:
  • UI(Harbor-ui):提供图形化界面,帮助用户管理 Registry 上的镜像(image), 并对用户进行授权。
  • Webhook:为了及时获取 registry 上image状态变化的情况,在Registry上配置webhook,把状态变化传递给UI模块。
  • Token 服务:负责根据用户权限给每个Docker push/pull命令签发token.Docker客户端向 Regiøstry服务发起的请求,如果不包含token,会被重定向到这里,获得token后再重新向 Registry进行请求。
  1. Database(Harbor-db):为 core services 提供数据库服务,负责储存用户权限、审计日志、Docker image 分组信息等数据。
  2. Log collector(Harbor-log):为了帮助监控 Harbor 运行,负责收集其他组件的log,供日后进行分析。(这就是一个日志平台)
4.部署环境
角色 操作系统 主机名 IP地址 软件
仓库服务 Cenots7.8-1 barbor01 192.168.200.101 docker-ce&docker-compose&harbor-offline
仓库服务 Centos7.8-2 barbor02 192.168.200.102 docker-ce&docker-compose&harbor-offline
Docker客户端 Centos7.8-3 client 192.168.200.103 docker-ce

安装docker

wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

yum -y install yum-utils device-mapper-persistent-data lvm2

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

yum install docker-ce

systemctl start docker
systemctl enable docker

部署compose服务:

下载compos拖进xshell添加x权限,移动到可执行目录下 echo $PATH

部署harbor服务:

Harbor被部署为多个Docker容器,因此可以部署在任何支持Docker的linux发行版上,目标主机需要安装Python、Docker和Docker Compose。

下载Harbor安装程序(俩台harbor主机)docker版本太低安装不了

1.解压
[root@harbor01 ~]# tar -xvf harbor-offline-installer-v1.5.0.tgz -C /usr/local/

2.修改Harbor参数文件 先改个名
mv harbor.yml.tmpl harbor.yml
vim /usr/local/harbor/harbor.yml
hostname = 192.168.200.101  #改为本主机ip
https:    #如果没有http认证证书那就注释掉

//vim内批量注释和批量删除 在末行模式下
注释:ctrl+v 选中要注释的(上下键)开大写 i键 #键 关大写 esc键
取消注释:ctrl+v 然后选中要注释的(上下键) x键

3.启动并安装Harbor
cd /usr/local/harbor
bash -x install.sh
查看harbor启动镜像
docker-compose ps

4.如果一切正常,浏览器访问 本机ip 
默认管理员的用户和密码是 admin/Harbor12345

你可能感兴趣的:(docker,容器)