自动化运维之docker上——docker简介、docker的安装、docker镜像
目录一、docker容器(Container)简介1、什么是docker2、传统虚拟化与docker的差别?3、docker容器的优势4、容器是如何工作的二、docker的安装1、配置docker的软件源2、安装docker-ce3、启动docker4、查看docker信息5、docker中镜像的查询及下载6、docker中镜像的使用7、测试三、docker的镜像1、镜像的分层结构2、镜像的构建—
目录
容器删除后重新启动,之前创建的文件没了。因此需要保存对容器的更改。
2、优化实验一:减少镜像的层数,清理镜像构建的中间产物对构建的影响。
一、docker容器(Container)简介
1、什么是docker
Docker就好比传统的货运集装箱
Docker是管理容器的引擎。 Docker为应用打包、部署平台,而非单纯的虚拟化技术。
2、传统虚拟化与docker的差别?
3、docker容器的优势
对于开发人员:Build once、Run anywhere。
对于运维人员:Configure once、Run anything。
4、容器是如何工作的
客户端——>Docker引擎——>仓库
二、docker的安装
1、配置docker的软件源
curl https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -o docker-ce.repo
修改软件docker软件源,只保留上一步中下载的第一个软件源路径,并取消校验。
这样配置的docker软件源没有解决依赖性,因此还需要进一步配置centos源20
wget https://mirrors.aliyun.com/repo/Centos-7.repo
对Centos-7.repo软件源做如下更改(其余部分删除)
软件源配置完成后,更新软件源列表,即可看到docker软件仓库和centos7的软件仓库。
2、安装docker-ce
yum install -y docker-ce
注意:这里有个小建议。在安装时可以把从外部下载的依赖包保存在自己的软件源中,再次安装时可以从自己的软件源中调取。否则每次都从网络上下载依赖包会比较麻烦。
解决办法:更改yum配置,保存缓存,那么在安装完软件后会将软件包保存在指定目录下。
3、启动docker
systemctl enable --now docker #启动并设置docker开机自启动
4、查看docker信息
docker info #查看docker信息
5、docker中镜像的查询及下载
docker search yakexi007 #查询容器
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
yakexi007/game2048 0
yakexi007/mario 0
yakexi007/nginx 0
yakexi007/base-debian10 0
docker pull yakexi007/game2048 #拉取容器中的镜像
docker images #查看本地有哪些镜像
注意:docker的所有数据全部保存在目录</var/lib/docker/>中。
6、docker中镜像的使用
docker run -d --name demo -p 80:80 yakexi007/game2048 #运行镜像
-d:打入后台; --name:项目名取为demo(加上名字后方便操作,不加时会随机创建一个名称);
-p:端口映射(宿主机的80端口映射到docker的80端口)
docker ps #查看正在运行的镜像
7、测试
在浏览器中访问虚拟机IP,可以访问正在运行中的docker
三、docker的镜像
1、镜像的分层结构
共享宿主机的kernel;base镜像提供的是最小的Linux发行版;同一docker主机支持运行多种Linux发行版;采用分层结构的最大好处是:共享资源
Copy-on-Write 可写容器层;容器层以下所有镜像层都是只读的;docker从上往下依次查找文件;容器层保存镜像变化的部分,并不会对镜像本身进行任何修改;一个镜像最多127层。
2、镜像的构建——三部曲
Docker commit构建新镜像三部曲:
运行容器;修改容器;将容器保存为新的镜像(运行——>修改——>提交)
先拉取一个新镜像busybox
(1)容器的创建(运行)与删除
运行busybox镜像,镜像在运行时会占用终端,并且可以在shell中交互创建文件。<Ctrl>+<d>会退出容器进程
docker run -it --name demo busybox #运行容器
重新启动容器,已经在后台运行,通过“attach”进入容器内部后,可以通过<Ctrl>+<p>+<q>将容器打入后台。
docker start demo #启动容器
docker attach demo #提取正在后台运行的容器
关闭容器,将会把后台运行的容器关闭,重新查看进程,确认demo容器已经不在后台运行。
docker stop demo #关闭容器
(2)容器的更改
容器删除后重新启动,之前创建的文件没了。因此需要保存对容器的更改。
进入busybox容器内部,创建一个file1文件。退出后将更改提交(commit),并重新命名为“demo:v1”那么“demo:v1”就是在“busybox”的基础上新加了一层。通过docker history命令可以查看到两个容器的差别。
删除掉现有的容器demo,进入新的容器“demo:v1”后,可以看到之前的更改了。
(3)镜像的删除
镜像的删除有两种方法,可以指定镜像名称,也可以指定镜像ID
docker rmi demo:v1 #指定镜像名称
docker rmi f4ac6fa47a2a #指定镜像ID
此方法的缺点: 效率低、可重复性弱、容易出错;使用者无法对镜像进行审计,存在安全隐患
3、镜像的构建——Dockerfile文件
原理:Dockerfile文件中命令的每一层都是逐层提交的。即将构建的操作逻辑以文件的形式表现出来。
(1)编写Dockerfile文件
vim Dockerfile #编辑Dockerfile
FROM busybox
RUN touch file1
Run echo westos > index.html
docker build -t demo:v1 . #构建Dockerfile
.表示构建的所有数据来自于当前目录
(2)查看镜像
通过Dockerfile文件生成镜像后,如果只是要进入查看后退出,可以按照如下命令。
docker run --rm -it demo:v1 #退出时删除容器
通过“docker history”可以看到Dockerfile文件中每一步的执行细节。退出容器后删除,再次查看进程已经查不到了。
(3)镜像的缓存特性
在上一个Dockerfile的最后再创建一个文件file2,构建时可以看到,前边几步在构建“demo:v1”时已经执行过了,所以构建“demo:v2”时不会再次执行,会使用上一次执行的缓存。
4、Dockerfile详解
(1)Dockerfile官方文档:
(2)Dockerfile常用指令
FROM | 指定base镜像,如果本地不存在会从远程仓库下载。 |
MAINTAINER | 设置镜像的作者,比如用户邮箱等。 |
COPY | 把文件从build context复制到镜像 支持两种形式:COPY src dest 和 COPY ["src", "dest"] src必须指定build context中的文件或目录 |
ADD | 用法与COPY类似,不同的是src可以是归档压缩文件,文件会被自动解压到dest,也可以自动下载URL并拷贝到镜像: ADD html.tar /var/www ADD http://ip/html.tar /var/www |
ENV | 设置环境变量,变量可以被后续的指令使用: ENV HOSTNAME sevrer1.example.com |
EXPOSE | 如果容器中运行应用服务,可以把服务端口暴露出去: EXPOSE 80 |
VOLUME | 申明数据卷,通常指定的是应用的数据挂在点: VOLUME ["/var/www/html"] |
WORKDIR | 为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工作目录,如果目录不存在会自动创建。 |
RUN | 在容器中运行命令并创建新的镜像层,常用于安装软件包: RUN yum install -y vim |
CMD 与 ENTRYPOINT | 这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。 docker run后面的参数可以传递给ENTRYPOINT指令当作参数。 Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后一个有效。 |
COPY指令:
注意:COPY指令执行时,目标文件只能用相对路径,不能用绝对路径。因此要处理的文件应该和Dockerfile文件放在同一目录下。
vim Dockerfile #编辑Dockerfile文件
FROM busybox
COPY index.html / #COPY命令
docker build -t demo:v1 . #构建为demo:v1
docker history demo:v1 #查看demo:v1的构建步骤
docker run --rm -it demo:v1 #仅查看容器demo:v1的执行结果
ADD指令:
此例中,由于所有指令都是基于第一步“FROM busybox”的镜像,如果busybox镜像中不含有该指令,那么将无法执行。对压缩文件来说,busybox中如果没有tar或者gzip命令,将无法处理压缩文件。因此引入“ADD”指令,执行后可以将压缩文件直接解压成目录。
注意:原文件可以来自本机,也可以来自网络
cat Dockerfile
FROM busybox
COPY index.html /
ADD nginx-1.20.2.tar.gz /
docker build -t demo:v2 .
docker history demo:v2
docker run --rm -it demo:v2 #仅执行,不构建
ENV指令:
设置环境变量,变量可以被后续的指令使用
EXPOSE指令:
一般在docker中封装了一些服务,EXPOSE用于将这些服务的端口设置成对外开放。
以超级玛丽游戏为例:
docker search yakexi007 #查找镜像
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
yakexi007/game2048 0
yakexi007/mario 0
yakexi007/nginx 0
yakexi007/base-debian10 0
yakexi007/base-debian11 0
docker pull yakexi007/mario #拉取镜像
docker history yakexi007/mario:latest #查看此镜像的详细信息
docker run -d --name demo -p 80:8080 yakexi007/mario
#后台运行,并将镜像中的8080端口映射为宿主机的80端口
后台运行后,在浏览器访问宿主机的80时,实际上访问的是容器内的8080。可以看到正在运行的镜像。
VOLUME指令:
申明数据卷,通常指定的是应用的数据挂载点。用于分离容器和数据的,可以是本地,也可以是远程。(相当于数据直接写入宿主机)
由于容器的文件系统是比较慢的,因此通过此方式,将容器中的文件直接挂载到宿主机中,和宿主机中的文件系统保持一致,可以加快文件读写速度。
cat Dockerfile
FROM busybox
VOLUME /data #创建卷
docker build -t demo:v3 . #构建为demo:v3
docker history demo:v3
docker run -it --name demo1 demo:v3 #运行容器并命名为demo1
运行容器后,在卷目录“/data”下新建文件file1,可以查看到卷中内容已发生改变。
docker inspect demo1 #查看demo1的详细信息
表示宿主机中的这个目录实际上挂载的是容器中的“/data”目录下。
进入此目录下,可以看到之前在容器内创建的文件。且映射的这两个目录是同步的。在宿主机的此目录下创建file2,重新进土容器后,也可以在该卷中看到file2.
VOLUME的删除:删除容器时,创建的卷不会一起删掉,因此需要单独删除
[root@server1 docker]# docker volume ls
DRIVER VOLUME NAME
local bdf969483abfb346f3f51ae50655cc4949fc521a5696a7ee043e9b59163c439a
[root@server1 docker]# docker volume rm bdf969483abfb346f3f51ae50655cc4949fc521a5696a7ee043e9b59163c439a
WORKDIR指令:
为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工作目录,如果目录不存在会自动创建。(一般用户切换路径)
RUN指令:
在容器中运行命令并创建新的镜像层,常用于安装软件包:
RUN yum install -y vim
CMD 与 ENTRYPOINT 指令:
cat Dockerfile
FROM busybox
CMD echo "hello world" #CMD指令
docker build -t demo:v4 . #构建demo:v4
docker run --rm demo:v4 #运行后删除(仅查看运行结果)
hello world #运行结果
CMD里可以写多个,但只有最后一个生效。
书写格式:一般有shell和exec两种书写格式。
Shell和exec格式的区别为:
ENTRYPOINT echo "hello, $name"
Shell格式底层会调用/bin/sh -c来执行命令,可以解析变量,而下面的exec格式不会:ENTRYPOINT ["/bin/echo", "hello, $name"]
需要改写成以下形式:ENTRYPOINT ["/bin/sh", "-c", "echo hello, $name"]
# cat Dockerfile
FROM busybox
CMD echo "hello world" #shell格式
CMD echo "hello $hostname" #shell格式(解析变量)
CMD ["/bin/sh", "-c", "echo hello $hostname"] #exec格式
CMD 与 ENTRYPOINT 区别:
一般情况下,两个命令可以相互替换。区别在于,CMD可以被覆盖而ENTRYPOINT不能被覆盖。
已CMD命令结尾时,Dockerfile默认输出为“hello world”。先构建,再运行,在运行时、传入参数“linux”,这个参数将会覆盖原文件中的CMD命令“world”,输出变为“hello linux”。
[root@server1 docker]# cat Dockerfile
FROM busybox
ENTRYPOINT ["/bin/echo", "hello"]
CMD ["world"]
[root@server1 docker]# docker build -t demo:v1 . #构建
[root@server1 docker]# docker run --rm demo:v1 #运行
hello world
[root@server1 docker]# docker run --rm demo:v1 linux #运行时传参
hello linux
一般要进入某个容器而不运行时,可以在运行命令的最后加上“bash”,则会替换掉原本的CMD命令。
docker run --rm -it demo:v3 docker run --rm -it demo:v3 bash
(3)Dockerfile实践
#Dockerfile文件内容
#vim Dockerfile
1 FROM centos:7
2 ADD nginx-1.20.2.tar.gz /mnt
3 WORKDIR "/mnt/nginx-1.20.2"
4 RUN yum install -y gcc make pcre-devel zlib-devel
5 RUN ./configure --prefix=/usr/local/nginx
6 RUN make
7 RUN make install
8 EXPOSE 80
9 VOLUME /usr/local/nginx/html
10 CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
docker build -t demo:v1 . #构建
docker run -d --name demo demo:v1 #运行
[root@server1 docker]# docker ps #查看是否运行
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8b6a5b3e6579 demo:v1 "/usr/local/nginx/sb…" 6 seconds ago Up 6 seconds 80/tcp demo
[root@server1 docker]# docker inspect demo | grep IPAddress #查看容器详细信息
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
"IPAddress": "172.17.0.2",
[root@server1 docker]# curl 172.17.0.2 #测试
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
因为有卷VOLUME的存在,所以可以直接更改宿主机的发布目录。发布目录可以通过“docker inspect demo”查找到。更改发布文件后,再次访问nginx的IP,可以看到修改成功。
5、镜像的优化
1、镜像的优化原则
选择最精简的基础镜像 |
减少镜像的层数 |
清理镜像构建的中间产物 |
注意优化网络请求 |
尽量去用构建缓存 |
使用多阶段构建镜像 |
2、优化实验一:减少镜像的层数,清理镜像构建的中间产物对构建的影响。
在上一步实验的基础上做如下更改:
#编辑Dockerfile文件
# vim Dockerfile
1 FROM centos:7
2 ADD nginx-1.20.2.tar.gz /mnt
3 WORKDIR "/mnt/nginx-1.20.2"
4 RUN yum install -y gcc make pcre-devel zlib-devel && ./configure --prefix=/usr/local/nginx && make && make install && rm -fr /mnt/nginx-1.20.2
5 EXPOSE 80
6 VOLUME /usr/local/nginx/html
7 CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
优化后的容器为demo:v2,和未优化的demo:v1相比,占用空间有所减少。
3、优化实验二:使用多阶段构建镜像
以下为例,第一阶段构建,构建完成后将产生的二进制文件直接复制到“/usr/local/nginx”目录下。
#编辑Dockerfile文件
#vim Dockerfile
1 FROM centos:7 as build
2 ADD nginx-1.20.2.tar.gz /mnt
3 WORKDIR "/mnt/nginx-1.20.2"
4 RUN yum install -y gcc make pcre-devel zlib-devel && ./configure --prefix=/usr/local/nginx && make && make install && rm -fr /mnt/nginx-1.20.2
5
6
7 FROM centos:7
8 COPY --from=build /usr/local/nginx /usr/local/nginx
9 EXPOSE 80
10 VOLUME /usr/local/nginx/html
11 CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
重新构建的镜像命名为“demo:v3”,占用空间进一步减小。
4、 优化实验三:选择最精简的基础镜像,使用多阶段构建镜像
注意:这里用到的nginx为1.18.0版本的,所以在执行前需要先拉取这个版本的nginx
<docker pull nginx:1.18.0>
#编辑Dockerfile文件
#vim Dockerfile
1 FROM nginx:1.18.0 as base
2
3 # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
4 ARG TIME_ZONE
5
6 RUN mkdir -p /opt/var/cache/nginx && \
7 cp -a --parents /usr/lib/nginx /opt && \
8 cp -a --parents /usr/share/nginx /opt && \
9 cp -a --parents /var/log/nginx /opt && \
10 cp -aL --parents /var/run /opt && \
11 cp -a --parents /etc/nginx /opt && \
12 cp -a --parents /etc/passwd /opt && \
13 cp -a --parents /etc/group /opt && \
14 cp -a --parents /usr/sbin/nginx /opt && \
15 cp -a --parents /usr/sbin/nginx-debug /opt && \
16 cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \
17 cp -a --parents /lib/x86_64-linux-gnu/libpcre.so.* /opt && \
18 cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
19 cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \
20 cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \
21 cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \
22 cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \
23 cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
24 cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
25 cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime
26
27 FROM gcr.io/distroless/base-debian10
28
29 COPY --from=base /opt /
30
31 EXPOSE 80 443
32
33 ENTRYPOINT ["nginx", "-g", "daemon off;"]
修改完Dockerfile文件后,构建为“demo:v4”后测试。可以看到此优化方法构建的镜像"demo:v4"占用空间已经大大减小。
docker build -t demo:v4 . #构建
docker run -d --name demo demo:v4 #启动
[root@server1 docker]# docker ps #查看容器进程
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
715599f41644 demo:v4 "nginx -g 'daemon of…" 2 minutes ago Up 2 minutes 80/tcp, 443/tcp demo
测试:可以正常访问nginx
四、docker命令的常用参数
docker search busybox(镜像名) | 查询镜像 |
docker pull busybox(镜像名) | 拉取镜像 |
docker images | 显示所有镜像 |
docker ps | 显示后台运行的镜像 |
docker run -d --name demo -p 80:80 yakexi007/game2048(镜像名) | 运行镜像 |
docker rm -f demo | 删除镜像 |
docker history yakexi007/game2048(镜像名) | 查看镜像的构建历史 |
docker inspect yakexi007/game2048:latest(镜像名) | 查看镜像的具体信息 |
docker container prune | 删除已经退出的容器 |
docker load -i base-debian10.tar (镜像名) | 导入本地镜像 |
docker tag gcr.io/distroless/base-debian10 zzh981030/base-debian10:latest | 重新给镜像打标签 |
五、本章总结
1、在安装好docker后,查看docker信息。显示docker的网桥连接有问题,这是因为火墙权限引起的。
解决办法:手动设置网桥选项
#编辑system配置文件
[root@server2 ~]# vim /etc/sysctl.d/docker.conf
#system内容如下
[root@server2 ~]# cat /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
#重新载入system配置,使之生效
[root@server2 ~]# sysctl --system
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
再次查看,已没有此报错
2、导入本地镜像包
docker load -i base-debian10.tar (镜像名)
3、打包镜像到本地
docker save -o busybox:1.27.tar busybox:1.27(镜像名)
更多推荐
所有评论(0)