Docker的安装部署、镜像构建与优化

本文介绍了Docker的基本概念、容器与虚拟机的区别、Docker的安装部署步骤,以及如何通过Dockerfile构建和优化镜像。通过实例展示了Docker在2048小游戏和Ubuntu环境中的应用,强调了Docker的轻量级和高效性,讨论了Dockerfile的使用技巧和镜像优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.什么是Docker?

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
一个完整的Docker有以下几个部分组成:
  DockerClient客户端
  Docker Daemon守护进程
  Docker Image镜像
  DockerContainer容器
起源
  Docker 是 PaaS 提供商 dotCloud 开源的一个基于 LXC 的高级容器引擎,源代码托管在 Github 上, 基于go语言并遵从Apache2.0协议开源。
  Docker自2013年以来非常火热,无论是从 github 上的代码活跃度,还是Redhat在RHEL6.5中集成对Docker的支持, 就连 Google 的 Compute Engine 也支持 docker 在其之上运行。
    Docker是一个命令行工具,它提供了中央“docker”执行过程中所需的所有工具。这使得Docker的操作非常简单。
Docker 架构
  Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。Docker 容器通过 Docker 镜像来创建。容器与镜像的关系类似于面向对象编程中的对象与类。

Docker面向对象
容器对象
镜像

    Docker采用 C/S架构 Docker daemon 作为服务端接受来自客户的请求,并处理这些请求(创建、运行、分发容器)。 客户端和服务端既可以运行在一个机器上,也可通过 socket 或者RESTful API 来进行通信。
  Docker daemon 一般在宿主机后台运行,等待接收来自客户端的消息。 Docker 客户端则为用户提供一系列可执行命令,用户用这些命令实现跟 Docker daemon 交互。

2.容器和虚拟机的区别

容器特点:容器共享宿主机的操作系统,容器的迁移非常方便,可以迁移到任何地方,只需要将容器拷贝到你的u盘,容器基本上是秒级部署,单台主机可以支持上千个容器
虚拟机原理:在宿主主机上运行虚拟机的操作系统,相当于再启动了一个主机,镜像比较大,而且操作系统会占用额外的cpu、内存、硬盘,底层必须要有qemu,就是内核的虚拟化、kvm的支持,可以做到完全隔离,而容器只能做到安全隔离

我们用的传统虚拟机如 VMware , VisualBox 之类的需要模拟整台机器包括硬件,每台虚拟机都需要有自己的操作系统,
虚拟机一旦被开启,预分配给它的资源将全部被占用。 每一台虚拟机包括应用,必要的二进制和库,以及一个完整的用户操作系统。
而容器技术是和我们的宿主机共享硬件资源及操作系统,可以实现资源的动态分配。
容器包含应用和其所有的依赖包,但是与其他容器共享内核。容器在宿主机操作系统中,在用户空间以分离的进程运行
容器技术是实现操作系统虚拟化的一种途径,可以让您在资源受到隔离的进程中运行应用程序及其依赖关系。
通过使用容器,我们可以轻松打包应用程序的代码、配置和依赖关系,将其变成容易使用的构建块,
从而实现环境一致性、运营效率、开发人员生产力和版本控制等诸多目标。
容器可以帮助保证应用程序快速、可靠、一致地部署,其间不受部署环境的影响

3.Docker的安装部署和简单应用(2048小游戏,ubuntu)

Docker的安装启动
(1)从物理机上获取安装docker时所需要的安装包
docker-ce-18.09.6-3.el7.x86_64.rpm
docker-ce-cli-18.09.6-3.el7.x86_64.rpm
containerd.io-1.2.5-3.1.el7.x86_64.rpm
container-selinux-2.21-1.el7.noarch.rpm
在这里插入图片描述
在这里插入图片描述
(2)启动 docker,设置为开机自启动
systemctl start docker
systemctl enable docker
在这里插入图片描述
管理docker常用的基础命令

docker load -i ubuntu.tar导入镜像
docker run -it --name vm1 ubuntu创建容器(以ubuntu镜像为模板)
docker ps查看容器状态
docker ps -a查看容器状态(包括不活跃的容器)
docker attach vm1连接容器
docker top vm1查看容器进程
docker logs vm1查看容器指令输出 -f 参数可以实时查看
docker inspect vm1查看容器详情
docker stats vm1查看容器资源使用率
docker diff vm1查看容器修改
docker stop vm1停止容器
docker start vm1启动容器
docker kill vm1强制结束容器进程
docker rm vm1删除容器
docker rmi mirror删除镜像

删除镜像使用rmi,删除容器使用rm
Docker的应用
实例一:利用容器简单搭建一个2048小游戏
(1)从物理机上获取2048小游戏的镜像tar包到server1
在这里插入图片描述
(2)docker命令导入镜像game2048.tar
docker load -i game2048.tar
在这里插入图片描述
docker run -d --name game1 -p 80:80 game2048 后台运行容器 (-d后台运行,-p端口映射,宿主主机80端口和容器80端口)
docker ps 查看当前运行的容器
docker ps -a 查看所有的容器
docker images 查看系统存在的镜像
du -sh game2048.tar查看tar包大小
在这里插入图片描述
(3)在浏览器访问server1的ip,前提条件是server1的80端口没有被占用,这样就可以通过server1访问容器vm1的80端口
输入server1的ip:172.25.254.1,可以看到2048的游戏界面
在这里插入图片描述
docker info 查看 docker 信息
有警告WARNING
在这里插入图片描述

vim /etc/sysctl.d/docker.conf 	##解决docker信息中出现的警告
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
sysctl --system		##使生效

在这里插入图片描述
实例二:利用docker创建一个交互式容器
(1)从物理机获取ubuntu的镜像到server1
导入镜像
在这里插入图片描述
(2)查看镜像大小并运行

docker run -it --name vm3 ubuntu	##创建一个vm1的容器,-it表示打开交互式docker界面(ubuntu自带,rhel镜像需要在后面再加bash)

uname -r 容器vm1的内核版本与宿主机的内核版本一致
在容器中建立文件file1、file2
在这里插入图片描述
(3)删除容器,重新运行容器,刚才建立的文件不存在了
容器类似于快照,可以随时还原
在这里插入图片描述
docker所有的数据都存放在/var/lib/docker目录中
在这里插入图片描述

4.镜像的构建

构建一个新的镜像有两种方式:docker commit 和 Dockerfile
1、docker commit(不推荐使用)
(1)获取一个镜像busybox.tar,linux系统基础的文件系统, 适合从零开始构建镜像
在这里插入图片描述
(2)docker load -I busybox.tar 导入busybox的镜像
docker run -it --name vm1 busybox 运行容器
vi testfile 编辑一个文件
快捷键:ctrl+p+q 退出容器但不关闭
docker ps
只显示了sh,看不到操作的镜像一般是不会用的,必须让其他人看到你做了什么操作,证明我们已经把这个文件封装到镜像里去了
docker attach vm1 重新连接到容器
在这里插入图片描述
(3)docker commit vm1 test:v1 提交更改过的容器
test比busybox多了一步sh
在这里插入图片描述
(4)重新运行更改后封装的容器
编辑的testfile文件还存在
在这里插入图片描述
2、Dockerfile
Dockerfile相当于ansible中的playbook,把你像构建镜像的操作写在文件里,根据这个文件构建镜像,这样可以看到新镜像构建的过程

mkdir docker 	##新建目录docker来放dockerfile, docker 引擎会提交这个目录下的所有数据,该目录下不要放其他文件
vim Dockerfile
 FROM busybox 	##指定以busybox镜像为基础 
 RUN echo testfile > file1	##操作
 RUN echo testfile > file2
docker build -t test:v2 .	##构建镜像v2,表示提交当前目录中的内容
		##第一步,基础容器;第二步,添加第一条命令后的容器;第三步,添加第二条命令后的容器

在这里插入图片描述
在这里插入图片描述

docker history test:v2 	##可以看到新建镜像过程的全部操作

在这里插入图片描述
再次更改Dockerfile,构建容器,如果有相同的镜像层,它会从缓存中读取,容器构建速度变快
在这里插入图片描述
在这里插入图片描述

docker rmi test:v1	##删除镜像

在这里插入图片描述

5.Dockerfile中的一些用法

1、COPY和ADD用法
COPY可以把本机的文件拷贝到我们的容器中,方便部署

vim Dockerfile
FROM busybox 
COPY testfile /tmp	##本机文件拷贝到容器中的/tmp目录
echo helloworld > testfile 	##建立本地文件
docker build -t test:v1 .	##构建镜像
docker run -it --name vm1 test:v1	##运行容器

在这里插入图片描述
在这里插入图片描述
ADD和COPY用法一样,它在拷贝文件的同时可以解压文件
获取一个nginx安装包,编辑Dockerfile

vim Dockerfile
FROM busybox 
COPY testfile /tmp
ADD nginx-1.16.1.tar.gz /tmp	##拷贝并解压文件
docker build -t test:v2 . 	##构建镜像
docker run -it --name vm1 test:v2	##运行容器,可以看到文件已经被解压

在这里插入图片描述
在这里插入图片描述
2、VOLUME(数据卷)用法

vim Dockerfile
FROM busybox 
COPY testfile /tmp
ADD nginx-1.16.1.tar.gz /tmp
VOLUME ["/data"] 	##在容器启动时会自动新建这个目录/data
docker build -t test:v3 .	##构建镜像
docker run -it --name vm2 test:v3	##运行容器

在这里插入图片描述

docker inspect vm2	##查看vm2信息,这个容器所对应的数据存放在 “Source”后的目录中,这个目录对应的就是容器里面的/data目录

在这里插入图片描述
在这里插入图片描述

docker attach vm2	##可以在/data看到在宿主机上新建的文件,在容器里也可以看到

在这里插入图片描述
容器中数据卷挂载到指定目录 -v

docker run -it --name vm2 -v /opt/data:/data test:v3 	##/opt/data是宿主机的目录(不存在时会自动新建),/data是容器对应的目录

在容器的/data目录中建立文件,指定的挂载目录下可以看到
在这里插入图片描述
3、WORKDIR用法
WORKDIR是在镜像中的工作目录,相当于cd
WORKDIR为 ADD、RUN、COPY 等命令设置在镜像中的工作目录,不存在会新建
CMD 和 ENTRYPOINT 都是用于设置容器启动后执行的命令,
但是 CMD 会被 docker run 后面的命令行覆盖,而 ENTRYPOINT 一定会被执行
docker run 后面的参数可以传递给 ENTRYPOINT 指令当作参数
Dockerfile 中只能指定一个 ENTRYPOINT,如果有多个,只有最后一个生效
Dockerfile的两种格式:shell、exec
(1)shell 格式

vim Dockerfile
FROM busybox 
ENV name world 	##定义变量 name,值为 world 
ENTRYPOINT echo "hello,$name" 	##使用变量
docker build -t test:v4 .
docker run --rm test:v4 ##–rm 表示这个容器在运行完之后把它删除(一次性容器)

在这里插入图片描述
(2)exec 格式
exec格式+ENTRYPOINT

vim Dockerfile
FROM busybox
ENV name world 
ENTRYPOINT ["/bin/sh","-c","echo hello,$name"]	##变量被成功解析
docker build -t test:v6 .
docker run --rm test:v6	

在这里插入图片描述
exec格式+CMD

vim Dockerfile
FROM busybox 
ENTRYPOINT ["/bin/echo","hello"] 
CMD ["world"]
docker build -t test:v7 .
docker run --rm test:v7 ##当 docker run命令行里没有指定命令时,CMD会执行,有的话CMD命令就会被覆盖

在这里插入图片描述

6.Dockerfile构建镜像的优化

镜像的优化:
选择最精简的基础镜像
减少镜像层数
清理镜像构建的中间产物
注意优化 网络请求
尽量用构建缓存
使用多阶段构建镜像

实验:
以rhel7镜像构建容器,并在容器中安装nginx的源码包
以此容器构建新的镜像并做优化
(1)获取rhel7镜像并导入
在这里插入图片描述
(2)编写Dockerfile

vim Dockerfile
FROM rhel7
EXPOSE 80 	##暴露的端口80
MAINTAINER wsp333@sina.com
COPY dvd.repo /etc/yum.repos.d/ 	##dvd.repo需要在同级目录
RUN rpmdb --rebuilddb 	##在yum之前重新构建 rpm 数据库 
RUN yum install -y gcc make pcre-devel zlib-devel 
ADD nginx-1.16.1.tar.gz /mnt 
WORKDIR /mnt/nginx-1.16.1
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc     ##关闭debug日志
RUN ./configure --prefix=/usr/local/nginx 
RUN make 
RUN make install 
ENTRYPOINT ["/usr/local/nginx/sbin/nginx" , "-g" , "daemon off;"]

在这里插入图片描述
在这里插入图片描述
(3)第一次构建镜像,查看大小为303M

docker build -t nginx:v1 .

优化1
再次编辑Dockerfile,清理镜像构建的中间产物,在使用 yum 安装软件包时会产生缓存,在/var/cache/yum 中清理 yum 缓存和编译后的目录

FROM rhel7
EXPOSE 80 	##暴露的端口80
MAINTAINER wsp333@sina.com
COPY dvd.repo /etc/yum.repos.d/ 	
RUN rpmdb --rebuilddb 	 
RUN yum install -y gcc make pcre-devel zlib-devel && yum clean all	##清理yum缓存
ADD nginx-1.16.1.tar.gz /mnt 
WORKDIR /mnt/nginx-1.16.1
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc    
RUN ./configure --prefix=/usr/local/nginx 
RUN make 
RUN make install 
RUN rm -fr /mnt/nginx-1.16.1	##清理编译后的目录
ENTRYPOINT ["/usr/local/nginx/sbin/nginx" , "-g" , "daemon off;"]

docker build -t nginx:v2 .
在这里插入图片描述第一次优化,查看大小为277M
在这里插入图片描述
优化2
将RUN都放在一行,减少镜像层数

FROM rhel7 
EXPOSE 80 
MAINTAINER wsp333@sina.com
COPY dvd.repo /etc/yum.repos.d/
ADD nginx-1.16.1.tar.gz /mnt 
WORKDIR /mnt/nginx-1.16.1
RUN rpmdb --rebuilddb && yum install -y gcc make pcre-devel zlib-devel && yum clean all &&./configure--prefix=/usr/local/nginx&&make&&makeinstall&&rm-fr/mnt/nginx-1.16.1
ENTRYPOINT ["/usr/local/nginx/sbin/nginx" , "-g" , "daemonoff;"] 

docker build -t nginx:v3 .
在这里插入图片描述
第二次优化,查看大小为258M
在这里插入图片描述
优化3
多阶段构建镜像
在构建 nginx 镜像时,最终只需要的是/usr/local/nginx 的二进制程序,其他过程都可以不要,那么我们可以把构建过程在一个镜像中完成,二进制程序放在一个新的镜像中,这样新的镜像就很小了

FROM rhel7 as build ##作为构建过程的镜像 
EXPOSE 80 
MAINTAINER wsp333@sina.com
COPY dvd.repo /etc/yum.repos.d/
ADD nginx-1.16.1.tar.gz /mnt 
WORKDIR /mnt/nginx-1.16.1
RUN rpmdb --rebuilddb && yum install -y gcc make pcre-devel zlib-devel && yum clean all &&./configure--prefix=/usr/local/nginx&&make&&makeinstall&&rm-fr/mnt/nginx-1.16.1

FROM rhel7 
EXPOSE 80 
MAINTAINER wsp333@sina.com
VOLUME ["/usr/local/nginx/html"]	##使用容器时可以在宿主机对容器内容进行发布 
COPY --from=build/usr/local/nginx/usr/local/nginx 	##拷贝 nginx二进制程序目录 
ENTRYPOINT ["/usr/local/nginx/sbin/nginx","-g","daemonoff;"]

docker build -t nginx:v4 .
在这里插入图片描述
第三次优化,查看大小为141M
在这里插入图片描述
优化4
使用更加精简的基础镜像
从底层优化
首先我们需要导入一个distroless和nginx镜像
distroless镜像只包含应用程序及其运行时依赖项,不包含程序包管理器、shell以及在标准Linux发行版中可以找到的任何其他程序
用distroless去除容器中所有不必要的东西

docker load -I nginx.tar	##导入 nginx 镜像
docker load -I distroless.tar	##导入 distroless 镜像

在这里插入图片描述
编写 Dockerfile

mkdir distroless
vim Dockerfile
FROM nginx as base

#https://en.wikipedia.org/wiki/List_of_tz_database_time_zones ARG 
Asia/Shanghai #修改时区

RUN mkdir -p /opt/var/cache/nginx &&\ 
cp -a --parents /usr/lib/nginx /opt &&\ 
cp -a --parents/usr/share/nginx /opt &&\ 
cp -a --parents/var/log/nginx /opt &&\ 
cp -aL --parents/var/run /opt &&\ 
cp -a --parents/etc/nginx /opt &&\ 
cp -a --parents/etc/passwd/opt &&\ 
cp -a --parents/etc/group /opt &&\ 
cp -a --parents/usr/sbin/nginx /opt &&\ 
cp -a --parents/usr/sbin/nginx-debug /opt &&\ 
cp -a --parents/lib/x86_64-linux-gnu/libpcre.so.* /op t&&\ 
cp -a --parents/lib/x86_64-linux-gnu/libz.so.* /opt &&\ 
cp -a --parents/lib/x86_64-linux-gnu/libc.so.* /opt &&\ 
cp -a --parents/lib/x86_64-linux-gnu/libdl.so.* /opt &&\ 
cp -a --parents/lib/x86_64-linux-gnu/libpthread.so.* /opt &&\ 
cp -a --parents/lib/x86_64-linux-gnu/libcrypt.so.* /opt &&\ 
cp -a --parents/usr/lib/x86_64-linux-gnu/libssl.so.* /opt &&\ 
cp -a --parents/usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt &&\ 
cp/usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime
FROM gcr.io/distroless/base
FROM gcr.io/distroless/base
COPY --from=base /opt /
EXPOSE 80 443
ENTRYPOINT ["nginx","-g","daemonoff;"]

在这里插入图片描述

docker build -t nginx:v5 .
docker run -d --name nginx nginx:v5
docker inspect nginx

在这里插入图片描述
第四次优化,查看大小为26.8M
在这里插入图片描述
在这里插入图片描述
能正常访问到Nginx默认发布页,证明容器镜像可以正常使用
在这里插入图片描述
查看IP
在这里插入图片描述

docker rm -f nginx
docker build -t nginx:v5 .
docker run -d -p 80:80 --name nginx ngin:5	##做端口映射,在浏览器上可以进行访问

在这里插入图片描述
在浏览器上访问宿主主机ip,可以访问到容器中的内容
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值