前言
为什么使用容器
随着业务的发展,系统逐渐从传统服务逐渐到微服务反向发展,其会面临以下问题:
1.上线流程繁琐:开发-》测试-》申请资源-》审批-》部署-》测试等环节
2.资源利用率低:普遍服务器利用率低,造成过多浪费
3.扩容/缩容不及时:业务高峰期扩容流程繁琐,上线不及时
4.服务器环境臃肿:服务器越来越臃肿,对维护、迁移带来困难
5.环境不一致性
容器和虚拟机的区别
对比 | 容器 | 虚拟 |
---|---|---|
启动速度运行性能磁盘占用数量 | 秒级 | 分钟级 |
隔离性操作系统封装程度 | 接近原生 | 5%左右损失 |
磁盘占有 | MB | GB |
数量 | 成百上千 | 一般几十台 |
隔离性 | 进程级 | 系统级(更彻底) |
操作系统 | 主要支持Linux | 几乎所有 |
封装程度 | 只打包项目代码和依赖关系,共享宿主机内核 | 完整的操作系统 |
容器提供一个基本的独立环境,实现容器隔离、资源限制,他主要解决应用层面问题,应用快速部署、高效管理
虚拟机是提升服务器资源利用率,他提供一个完全隔离的环境
什么是docker
docker是
C/S
架构的程序,docker的客户端向服务器端(也就是Docker的守护进程)发出请求,守护进程处理完所有的工作并返回结果;docker客户端向服务器端的访问既可以在本地也可以通过远程来访问
docker的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来。并且各种各样的货物被集装箱标准化了,集装箱和集装箱之间不会互相影响。那么我就不需要专门运送水果的船和专门运送化学品的船了。只要这些货物在集装箱里封装的好好的,那我就可以用一艘大船把他们都运走。docker就是类似的理念。现在都流行云计算了,云计算就好比大货轮。docker就是集装箱。
1.不同的应用程序可能会有不同的应用环境,比如.net开发的网站和php开发的网站依赖的软件就不一样,如果把他们依赖的软件都安装在一个服务器上就要调试很久,而且很麻烦,还会造成一些冲突。比如IIS和Apache访问端口冲突。这个时候你就要隔离.net开发的网站和php开发的网站。常规来讲,我们可以在服务器上创建不同的虚拟机在不同的虚拟机上放置不同的应用,但是虚拟机开销比较高。docker可以实现虚拟机隔离应用环境的功能,并且开销比虚拟机小,小就意味着省钱了。
2.你开发软件的时候用的是Ubuntu,但是运维管理的都是centos,运维在把你的软件从开发环境转移到生产环境的时候就会遇到一些Ubuntu转centos的问题,比如:有个特殊版本的数据库,只有Ubuntu支持,centos不支持,在转移的过程当中运维就得想办法解决这样的问题。这时候要是有docker你就可以把开发环境直接封装转移给运维,运维直接部署你给他的docker就可以了。而且部署速度快。
3.在服务器负载方面,如果你单独开一个虚拟机,那么虚拟机会占用空闲内存的,docker部署的话,这些内存就会利用起来。总之docker就是集装箱原理。
一、安装步骤
1.1 安装依赖
[root@save etc]# yum install -y yum-utils device-mapper-persistent-data lvm2
1.2 设置yum源
//使用官方源地址(比较慢)
[root@save etc]# yum-config-manager --add-repo http://download.docker.com/linux/centos/docker-ce.repo
//阿里云
[root@save etc]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
1.3 安装
[root@save etc]# yum install docker-ce-18.03.1.ce -y
1.4 配置镜像加速器
/etc/docker/daemon.json
{
"registry-mirrors": ["https://qyh9xq2x.mirror.aliyuncs.com"]
}
二、管理镜像
格式:docker image 指令
指令 | 描述 |
---|---|
Is | 列出本地存在的镜像 |
build | 构建镜像来自Dockerfile |
history | 查看镜像历史 |
inspect | 显示一个或多个镜像详细信息 |
pull | 从镜像仓库拉取镜像 |
push | 推送一个镜像到镜像仓库 |
rm | 移除一个或多个镜像 |
prune | 移除没有被标记或者没有被任何容器引用的镜像 |
tag | 创建一个引用源镜像标记目标镜像 |
save | 保存一个或多个镜像到一个tar归档文件 |
load | 加载镜像来自tar归档或标准输入 |
2.1 pull
如果本地用这个镜像的话,就不会去远程拉
[root@save ~]# docker image pull nginx:latest
Using default tag: latest
latest: Pulling from library/nginx
a076a628af6f: Pull complete
0732ab25fa22: Pull complete
d7f36f6fe38f: Pull complete
f72584a26f32: Pull complete
7125e4df9063: Pull complete
Digest: sha256:10b8cc432d56da8b61b070f4c7d2543a9ed17c2b23010b43af434fd40e2ca4aa
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
[root@save ~]# docker image pull nginx
Using default tag: latest
latest: Pulling from library/nginx
Digest: sha256:10b8cc432d56da8b61b070f4c7d2543a9ed17c2b23010b43af434fd40e2ca4aa
Status: Image is up to date for nginx:latest
docker.io/library/nginx:latest
2.2 查看镜像信息
[root@save ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest f6d0b4767a6c 2 months ago 133MB
[root@save ~]# docker image history nginx
IMAGE CREATED CREATED BY SIZE COMMENT
f6d0b4767a6c 2 months ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
<missing> 2 months ago /bin/sh -c #(nop) STOPSIGNAL SIGQUIT 0B
<missing> 2 months ago /bin/sh -c #(nop) EXPOSE 80 0B
<missing> 2 months ago /bin/sh -c #(nop) ENTRYPOINT ["/docker-entr… 0B
<missing> 2 months ago /bin/sh -c #(nop) COPY file:0fd5fca330dcd6a7… 1.04kB
<missing> 2 months ago /bin/sh -c #(nop) COPY file:0b866ff3fc1ef5b0… 1.96kB
<missing> 2 months ago /bin/sh -c #(nop) COPY file:e7e183879c35719c… 1.2kB
<missing> 2 months ago /bin/sh -c set -x && addgroup --system -… 63.7MB
<missing> 2 months ago /bin/sh -c #(nop) ENV PKG_RELEASE=1~buster 0B
<missing> 2 months ago /bin/sh -c #(nop) ENV NJS_VERSION=0.5.0 0B
<missing> 2 months ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.19.6 0B
<missing> 2 months ago /bin/sh -c #(nop) LABEL maintainer=NGINX Do… 0B
<missing> 2 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ADD file:422aca8901ae3d869… 69.2MB
[root@save ~]# docker image inspect nginx
//... 忽略
三、创建容器
语法:docker run [OPTIONS] IMAGE [COMMAND] [ARG…]
注意:COMMAND 默认为 /bin/bash,因此用户的输入是基于 bash shell 执行的
-d 后台运行容器,并返回容器ID
–name 为容器指定一个名称
-p 指定端口映射,格式为:主机(宿主)端口:容器端口.
-h 指定容器的hostname
以镜像nginx:latest创建并启动一个容器mynginx
[root@save ~]# docker run -d --name mynginx -p 88:80 -h web nginx:latest
[root@save ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2bc2e2d4dcb7 nginx:latest "/docker-entrypoint.…" 3 minutes ago Up 3 minutes 0.0.0.0:88->80/tcp mynginx
浏览器测试访问:http://192.168.93.222:88 成功
-a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
-d: 后台运行容器,并返回容器ID;
-i: 以交互模式运行容器,通常与 -t 同时使用;
-P: 随机端口映射,容器内部端口随机映射到主机的端口
-p: 指定端口映射,格式为:主机(宿主)端口:容器端口
-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
–name=“nginx-lb”: 为容器指定一个名称;
–dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
–dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
-h “mars”: 指定容器的hostname;
-e username=“ritchie”: 设置环境变量;
–env-file=[]: 从指定文件读入环境变量;
–cpuset=“0-2” or --cpuset=“0,1,2”: 绑定容器到指定CPU运行;
-m :设置容器使用内存最大值;
–net=“bridge”: 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
–link=[]: 添加链接到另一个容器;
–expose=[]: 开放一个端口或一组端口;
–volume , -v: 绑定一个卷
四、容器的管理
命令格式:docker container 指令
指令 | 描述 |
---|---|
Is | 列出容器 |
inspect | 查看一个或多个容器详细信息 |
exec | 在运行容器中执行命令 |
commit | 创建一个新镜像来自一个容器 |
cp | 拷贝文件/文件夹到一个容器 |
logs | 获取一个容器日志 |
port | 列出或指定容器端口映射 |
top | 显示一个容器运行的进程 |
stats | 显示容器资源使用统计 |
stop/start/restart | 停止/启动一个或多个容器 |
rm | 删除一个或多个容器 |
prune | 移除已停止的容器 |
4.1 Is
列出当前在运行的容器
[root@save ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2bc2e2d4dcb7 nginx:latest "/docker-entrypoint.…" 19 minutes ago Up 19 minutes 0.0.0.0:88->80/tcp mnginx
列出当前最近创建在运行的容器
[root@save ~]# docker container ls -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2bc2e2d4dcb7 nginx:latest "/docker-entrypoint.…" 20 minutes ago Up 20 minutes 0.0.0.0:88->80/tcp mnginx
显示所有的容器,包括未运行的
[root@save ~]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2bc2e2d4dcb7 nginx:latest "/docker-entrypoint.…" 22 minutes ago Up 22 minutes 0.0.0.0:88->80/tcp mnginx
706fef35a5db nginx "/docker-entrypoint.…" 49 minutes ago Exited (0) 42 minutes ago mynginx
7ba7a394f10e nginx "/docker-entrypoint.…" 30 hours ago Exited (0) 13 hours ago nginx
6673adcb8da4 nginx "/docker-entrypoint.…" 30 hours ago Exited (0) 13 hours ago festive_shtern
4.2 exec
在容器 mynginx 中以交互模式执行容器内 /root/runoob.sh 脚本
[root@save ~]# docker exec -it mynginx /bin/sh /root/runoob.sh
http://www.runoob.com/
4.3 run
在容器 mynginx 中开启一个交互模式的终端
-d: 后台运行容器,并返回容器ID;
-P: 随机端口映射,容器内部端口随机映射到主机的端口
-p: 指定端口映射,格式为:主机(宿主)端口:容器端口
–name=“nginx-lb”: 为容器指定一个名称;
-h “mars”: 指定容器的hostname;
-e username=“ritchie”: 设置环境变量;
–env-file=[]: 从指定文件读入环境变量;
[root@save ~]# docker run -d --name mnginx -p 88:80 -h web -e boy=xiaoming nginx:latest
2bc2e2d4dcb75176ea25fc8e0655ff156160210d1ef406cee95c841615e91d8b
[root@save ~]# docker container exec -it mnginx /bin/bash
root@web:/# hostname
web
root@web:/# echo $boy
xiaoming
4.4 cp
将宿主机文件拷贝到容器mnginx中
[root@save ~]# ll
-rw-------. 1 root root 1649 11月 27 15:37 anaconda-ks.cfg
-rw-r--r-- 1 root root 0 4月 7 23:00 demo.txt
[root@save ~]# docker cp demo.txt mnginx:/
[root@save ~]# docker exec mnginx ls
bin
boot
demo.txt
dev
docker-entrypoint.d
docker-entrypoint.sh
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
4.5 stop/start/restart
[root@save ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2bc2e2d4dcb7 nginx:latest "/docker-entrypoint.…" 34 minutes ago Up 34 minutes 0.0.0.0:88->80/tcp mnginx
[root@save ~]# docker stop mnginx
mnginx
[root@save ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@save ~]# docker container start mnginx
mnginx
[root@save ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2bc2e2d4dcb7 nginx:latest "/docker-entrypoint.…" 34 minutes ago Up 1 second 0.0.0.0:88->80/tcp mnginx
4.6 rm
删除已经停止的容器
[root@save ~]# docker container rm mnginx
Error response from daemon: You cannot remove a running container 2bc2e2d4dcb75176ea25fc8e0655ff156160210d1ef406cee95c841615e91d8b. Stop the container before attempting removal or force remove
[root@save ~]# docker container stop mnginx
mnginx
[root@save ~]# docker container rm mnginx
mnginx
强制删除在运行的容器
[root@save ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@save ~]# docker run -d --name mnginx -p 88:80 -h web -e boy=xiaoming nginx:latest
761f85d68d665a7fb1d192f8734712b17731f35bcbe3943d5ceb64878134c23e
[root@save ~]# docker container rm -f mnginx
mnginx
[root@save ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
五、容器数据的持久化
容器中的数据可以存储在容器层。但是将数据存放在容器层存在以下问题:
1、数据不是持久化。意思是如果容器删除了,这些数据也就没了
2、主机上的其它进程不方便访问这些数据
3、对这些数据的I/O会经过存储驱动,然后到达主机,引入了一层间接层,因此性能会有所下降
为了解决这些问题,Docker提供2种方式将数据从宿主机挂载到容器中
1、volumes:Docker管理宿主机文件系统的一部分(/var/ib/docker/volumes)。
2、bind mounts:将宿主机上的任意位置的文件或者目录挂载到容器中。
5.1 bind mounts 模式
//创建挂载目录
[root@save opt]# mkdir wwwroot
//把容器中的/usr/share/nginx/html目录挂载到宿主环境中的/opt/wwwroot/目录中
[root@save opt]# docker run -d --name mynginx -p 88:80 -h web -e boy=xiaoming -v /opt/wwwroot/:/usr/share/nginx/html nginx:latest
2f5db27d955badcf5f8fa918b4b29ec61b2217a51c89da3ab46bc3370de17c2f
[root@save opt]# ll wwwroot
总用量 0
注意这时候如果访问nginx访问,会出现403。
因为宿主环境中的/opt/wwwroot/目录覆盖了容器中的/usr/share/nginx/html目录,所以访问不到
[root@save opt]# cd wwwroot
[root@save wwwroot]# echo "<h1>clyu</h1>" > index.html
[root@save wwwroot]# ll
总用量 4
-rw-r--r-- 1 root root 14 4月 12 17:37 index.html
六、镜像的创建
有时候从Docker镜像仓库中下载的镜像不能满足要求,我们可以基于一个基础镜像构建一个自己的镜像两种方式:
6.1 更新镜像
使用
docker commit option 基础镜像名 自己的镜像名:版本号
命令
-a :提交的镜像作者;
-c :使用Dockerfile指令来创建镜像;
-m :提交时的说明文字;
-p :在commit时,将容器暂停。
[root@save ~]# docker run -d --name mynginx -p 88:80 -h web -e boy=xiaoming nginx:latest
e5726fd3d892740f26aa35225177e1bd911dbc77cf7d1ad21db6c90a9d7f7fb8
[root@save ~]# docker container exec -it mynginx /bin/bash
root@web:/usr/share/nginx/html# cd /usr/share/nginx/html
root@web:/usr/share/nginx/html# echo "<h1>clyu</h1>" >index.html
[root@save ~]# docker commit -a="clyu" -m="我的nginx" mynginx clyunginx:v1
sha256:d00d908b98af18fa68016094360904d5477bee67d83e1f23a2115789579ebc51
[root@save ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
clyunginx v1 d00d908b98af 13 seconds ago 133MB
nginx latest f6d0b4767a6c 3 months ago 133MB
6.2 Dockerfile
使用
docker build
命令,需要创建Dockerfile文件
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
在一个空目录下,新建一个名为 Dockerfile 文件,并在文件内添加以下内容:
FROM nginx
RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html
[root@save ~]# mkdir Dockerfile
[root@save ~]# cd Dockerfile/
[root@save Dockerfile]# vi Dockerfile
开始构建镜像
在 Dockerfile 文件的存放目录下,执行构建动作。
以下示例,通过目录下的 Dockerfile 构建一个 nginx:v3(镜像名称:镜像标签)。
注:最后的
.
代表本次执行的上下文路径 , 是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得
知这个路径后,会将路径下的所有内容打包。
解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。
如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。
注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。
[root@save Dockerfile]# docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM nginx
---> f6d0b4767a6c
Step 2/2 : RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html
---> Running in dddaea39fc3a
Removing intermediate container dddaea39fc3a
---> 696122cdb22c
Successfully built 696122cdb22c
Successfully tagged nginx:v3
[root@save Dockerfile]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v3 696122cdb22c 10 seconds ago 133MB
clyunginx v1 d00d908b98af 11 days ago 133MB
nginx latest f6d0b4767a6c 3 months ago 133MB