当前位置:首页 » 编程软件 » dockerfile脚本

dockerfile脚本

发布时间: 2022-12-09 14:01:40

A. DOCKER 总结

Docker 是一个开源的 应用容器引擎 ,让 开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 linux或Windows 机器上,也可以实现虚拟化 。容器是完全使用沙箱机制,相互之间不会有任何接口。

由于本地开发好的程序往往都需要部署到服务器上进行运行,这就导致了程序需要运行在不同的环境上,这通常是一个令人头痛的事情。在过去,开发团队需要清楚的告诉运维部署团队,其所使用的全部配置文件+所有软件环境。不过,即便如此,仍然常常发生部署失败的状况。

于是乎, 虚拟化 技术应运而生。开发团队将开发好的程序在虚拟机上运行,这样就能解决运维的问题。但是由于虚拟机技术过重的特性导致了其 资源占用多、冗余步骤多以及启动慢的缺陷 。而这个时候 一种新的虚拟化技术搭配上容器化的思想 的产品便出现了,而它就是Docker。

下图是虚拟机技术和容器化技术架构的对比。我们可以得出以下总结:

[图片上传失败...(image-efadd2-1643314980201)]
]( https://upload-images.jianshu.io/upload_images/646931-4b1431b77887632f.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 )

于是乎相比于虚拟机技术,容器化技术具有以下 优势:

相关网站

如下图所示,Docker使用客户端-服务器(C/S)架构模式,使用远程API来管理和创建Docker容器。服务器端分为Docker daemon, Image和Container三个部分。此外还有Docker Registry。

下面首先来介绍一下Docker中的主要概念

Docker的运行原理如下:客户端可以将docker命令发送到服务器端的Docker daemon上,再由Docker damon根据指令创建、选择或者从Docker仓库中拉取(pull)镜像。接着客户端可以通过镜像创建容器。当我们需要使用程序时,运行相应的容器即可。

小结

需要正确的理解仓储/镜像/容器这几个概念 :

在外面使用容器的时候,我们不希望容器中的数据在容器被删除后也一并删除了,这时候我们就可以 通过使用容器数据卷,将数据储存在本地并用Docker将其挂载到容器中,这样我们即使删除了容器,数据也依旧存在服务器中,也就实现了数据持久化。

特点

容器数据卷挂载命令(-v)

Dockerfile 挂载容器数据卷

我们除了可以从仓库中拉取镜像以外,我们也可以 自己创建镜像 ,这就要用到Docerfile。

dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本

构建步骤:

基础知识:

流程:

说明:

在实际场景中,我们会遇到 多个Container之间通讯 的问题。而Docker网络就是用于解决此问题的技术。docker会给每个容器都分配一个ip,且容器和容器之间是可以互相访问的。

Docker网络原理

每一个安装了Docker的linux主机都有一个docker0的虚拟网卡。这是个桥接网卡,使用了 veth-pair 技术 。Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据 Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网 关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

Docker容器网络就很好的利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并 让他们彼此联通(这样一对接口叫veth pair);

Docker中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为Linux是在内核中 进行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容 器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多。

[图片上传中...(image-41d42a-1642627027452-2)]

Docker Compose是一个用于定义并运行多容器应用的工具

Docker Compose的 步骤如下

NOTE: Compose :重要的概念。

docker-compose.yml编写

Note: docker-compose会自动为多容器之间创建网络,保证通讯。

Docker Swarm 是Docker 的集群管理工具。 它将 Docker 主机池转变为单个虚拟 Docker 主机。 Docker Swarm 提供了标准的 Docker API,所有任何已经与 Docker 守护程序通信的工具都可以使用 Swarm 轻松地扩展到多个主机。

Docker 是一个开源的 应用容器引擎 ,它的出现大大简化了运维的难度,提高了运维效率。过去我们需要在服务器上安装程序所需要的所有依赖,而如今我们只需要编写好docker-compose和Dockefile的脚本,就可以使程序一键跑通。在企业级的应用中,我们必然会惊颤使用到Docker和容器化技术。

狂神说

B. Docker multi-stage build机制

摘要: 随着17.05版本的发布,Docker对于镜像构建这块也作了一项重要更新,那就是 multi-stage build(多阶段构建),这对于长期因为构建镜像太大而困扰的小伙伴们来说真是雪中送炭。

随着17.05版本的发布,Docker对于镜像构建这块也作了一项重要更新,那就是 multi-stage build(多阶段构建),这对于长期因为构建镜像太大而困扰的小伙伴们来说真是雪中送炭。

在17.05版本之前,我们构建Docker镜像时,通常会采用两种方式:

这里以一个简单的java项目镜像构建为例来说明这两种构建方式,该项目仅仅包含一个App.java类:

这里是将所有的构建流程都编写在同一个Dockerfile中,但为了尽可能地减小镜像层次,我们将多个执行命令合并到同一个 RUN 指令中,同时我们需要自行清理掉源码目录文件以及编译后的临时目录文件,以防止源码泄露。

这里我们需要分为两个阶段:
1)编译打包 Dockerfile.2.1

2)构建镜像 Dockerfile.2.2

3)整合两个构建阶段 build.sh

这里我们编写了两个Dockerfile和一个Shell脚本,通过两阶段将最终镜像构建出来,但可预见的一个问题是,假若有多个项目彼此关联和依赖,就需要我们维护多个Dockerfile,或者需要编写更复杂的build.sh脚本,导致后期维护成本很高。

在Docker 17.05 多阶段构建推出之后,我们就可以很容易规避前面遇到的这些问题,并且只需要维护一个Dockerfile即可:

对于上面的Dockerfile是不是很熟悉,它仅仅是将第二种方式中的两个Dockerfile合并到同一个Dockerfile中,同时在构建过程中自动帮您完成了build.sh的流程。

对于multi-stage build,其关键点主要有两点:

同理,多阶段构建同样可以很方便地将多个彼此依赖的项目通过一个Dockerfile就可轻松构建出期望的容器镜像,而不用担心镜像太大、源码泄露等风险。

C. docker基于mysql:5.7构建镜像并初始化脚本

遇到的问题:内网环境,安装docker
解决方式:参考 https://segmentfault.com/a/1190000022982415

一、开始构建(编写Dockerfile)

二、构建

三、运行

四、验证数据脚本是否成功初始化(psp)

五、自动化执行脚本(init_mysql.sh)

D. Docker:容器管理(启动参数,查看容器和日志,进入和修改容器)

摘要: Docker

容器是一个精简版的操作系统,一般一个容器只运行一个应用,容器通过镜像创建,使用 docker run 命令创建,容器起到了 隔离 作用,容器和容器之间独享空间和网络等

容器的基本操作包括创建(启动),停止,重启,查看,检查等,容器通过镜像创建,使用 docker run 命令创建,需要指定run参数,镜像名,容器执行命令,语句格式如下

在实际使用中启动一个镜像,例如

-e 设置环境变量,格式是 -e k1=v1 -e k2=v2 ,使得在docker镜像中的程序能够直接访问到环境变量,同时可以作为配置参数放在docker run启动镜像的时候设置,而不是写死在dockerfile在build的过程中,-e和dockerfile中的 ENV 变量作用相同,当变量重名时-e替换ENV,下面测试一些-e参数,在Dockerfile指定环境变量

直接构建成容器

开启一个终端启动容器内部,打印指定的环境变量a

此时在run指令中增加-e设置环境变量,可见-e替换了Dockerfile中指定的环境变量

因为一个镜像可以启动多个容器,所以可以通过设置不同-e达到设置不同配置参数的目的,比如下一个例子在Dockerfile中设置和将环境变量写入yaml文件再供Python调用,执行的内容为打印yaml配置文件的参数内容,比如下面这个例子先看下目录结构

其中config.yml是一个空配置文件,在run.sh中先使用echo写入追加配置参数到config.yml在执行Python脚本

Dockerfile中启动run.sh脚本作为容器执行命令

在启动容器时,使用-e指定环境变量,在run.sh中echo将环境变量拿到和写入配置文件,测试多次以不同的配置参数启动容器如下

-v 设置挂载运行,将宿主机当前目录下的文件挂载到容器中/home目录下,例如

如果挂载的目录和Dockerfile中的COPY的目录不一致, -v会替代COPY或者ADD ,例如现在Docker中COPY一个文件到容器/home目录下

同目录下start.sh内容是打印1

构建镜像结束后,指定-v启动,起始挂载另外一个目录,目录下start.sh内容是打印2

docker run参数中最后的COMMAND会覆盖Dockerfile中指定的 CMD ,例如执行echo 2替换原始Dockerfile中的CMD echo 1,输出结果是2且执行完毕后退出

对于Dockerfile中的 ENTRYPOINT 指定的启动命令docker run的COMMAND不会覆盖,如果要覆盖Docker中的ENTRYPOINT需要指定docker run中的 --entrypoint 参数,格式是

测试一个Dockerfile输出1

在docker run中使用--entrypoint覆盖Dockerfile中的ENTRYPOINT

容器启动后通过 docker ps 或者 docker container ls 查看容器,可以增加额外参数比如 -a 显示所有容器,默认只显示运行的容器,可以增加 --no-trunc 参数使得显示结果不截断,例如

显示结果分别显示了容器的ID,镜像,执行命令,创建时间,状态,端口映射(宿主机->容器)和容器名称。对于已经运行的容器可以使用 docker stop 停止,如果在docker run时增加--rm参数则停止的容器保留不会自动删除,例如

除了docker stop命令还有一种停止容器的命令 docker kill ,相比于docker stop,docker kill是 强制立即停止 ,而docker stop是先给了容器10秒(默认)的时间,使得容器有一定的时间处理、保存程序执行现场, 优雅的退出程序 ,例如

在容器停止之后可以使用 docker start 再启动一个停止的容器,例如

除此之外可以使用 docker restart ,此时容器可以使停止的也可以是在运行中的,例如

查看容器详情使用 docker inspect ,比如

在以上截取的内容中展示了容器详情,包括容器id,创建时间,执行命令和参数,执行状态,容器pid,落脚点,环境变量,网络设置,端口映射等,也可以使用Go语言风格输出指定的详情,比如分别只看容器的pid和容器的执行命令

容器是一个操作系统,可以进入这个操作系统查看容器的运行情况,有多种方式进入容器,其中主要是使用 docker exec 进入容器,在一个运行中的容器中执行一个命令,使用 -it 并带有 /bin/bash 命令就可以进入容器,比如

除了/bin/bash也可以是其他命令挂载exec后面则可以直接对一个运行中的容器执行命令,比如查看容器的进入落脚点路径,容器中的内存情况

当容器以后台 -d 运行时,日志运行在容器内部,可以进入容器内部查看日志,也可以使用 docker logs 查看日志,以一个flask api接口的容器为例,日志写入文件,同时也会输出在flask的控制台

创建Dockerfile以及构建镜像,启动容器

启动一个脚本不断请求api接口

进入容器内部查看日志

另一种方式是直接使用 docker logs 命令,比如使用 -f 追踪输出,并且从最后的第1行开始输出

此时宿主机的logs目录下为空,容器中的logs目录下存在detail.log文件,如果使用 -v 将宿主机目录挂载到容器作为容器写入的目录,则容器中数据的变动会同步到本地,这样可以直接在本地查看日志,修改容器启动为 -v 挂载的形式

此时本地logs目录下开始产生日志,且这个日志和容器内的logs目录下一致

如果容器内的内容改变了,此时删除容器从镜像重新启动容器则改动的内容将不会存在,如果相对修改过的容器保留下来则可以从容器生成新的镜像,先测试以下容器内修改在删除的容器后将不再生效,在已有容器中使用pip安装Python包

此时退出容器,并且删除容器,最后从镜像重新生成容器

此时进入容器检查,并不存在pymongo包

如果要容器变化保存下来需要以这个新容器生成一个镜像,使用 docker commit ,语法如下

以新安装pymongo的容器为例,对新容器使用docker commmit

新生成的镜像叫做xiaogp/my_image_test:v2

从新镜像启动容器并进入容器查看存在新安装的pymongo

E. 基于docker的持续开发流程

相关步骤说明如下
(1) 开发。根据需求开发应用程序。
(2) 编写Dockerfile文件,Dockerfile是由一系列命令和参数组成的脚本,用来构建Image。
(3) 创建自定义镜像,基于docker build 命令构建
(4) 定义docker-compse,用来定义和运行多个docker应用程序。
(5) 启动docker应用,docker run。
(6) 测试,基于容器进行厕所,随时部署或销毁。
(7) 部署或继续开发。

(1) FROM: 它妈是谁(基础镜像)
(2) RUN: 开始动起来(执行命令,可以多次)
(3) COPY: 复制文件目录
(4) ADD: COPY加强版,支持远程复制和解压
(5) WORKDIR: CD伪装者(设置当前工作目录)
(6) CMD: 执行配置命令,如果多个,仅仅执行最后一个
(7) ENTRYPOINT: 容器启动后执行
(8) ENV: 环境变量
(9) EXPOSE: 专业敲墙打洞(开放端口)

F. 如何使用Docker构建运行时间较长的脚本

问题
让我们从这个我试图解决的问题开始。我开发了一个会运行很长时间的构建脚本,这个脚本中包含了很多的步骤。
这个脚本会运行1-2个小时。
它会从网络下载比较大的文件(超过300M)。
后面的构建步骤依赖前期构建的库。
但最最烦人的是,运行这个脚本真的需要花很长的时间。
文件系统是固有状态
我们一般是通过一种有状态的方式与文件系统进行交互的。我们可以添加、删除或移动文件。我们可以修改文件的 权限或者它的访问时间。大部分独立的操作都可以撤销,例如将文件移动到其它地方后,你可以将文件恢复到原来的位置。但我们不会通过快照的方式来将它恢复到 原始状态。这篇文章我将会介绍如何在耗时较长的脚本中充分利用快照这一特性。
使用联合文件系统的快照
Docker使用的是联合文件系统叫做AUFS(译者注:简单来说就是支持将不同目录挂载到同一个虚拟文件系统下的文件系统)。联合文件系统实现了Union mount。顾名思义,也就是说不同的文件系统的文件和目录可以分层叠加在单个连贯文件系统之上。这是通过分层的方式完成的。如果一个文件出现在两个文件系统,那最高层级的文件才会显示(该文件其它版本也是存在于层级中的,不会改变,只是看不到的)。
在Docker中,每一个在Union mount转哦给你的文件系统都被称为layers(层)。使用这种技术可以轻松实现快照,每个快照都是所有层的一个Union mount。
生成脚本的快照
使用快照可以帮助构建一个长时运行的脚本。总的想法是,将一个大的脚本分解为许多小的脚本(我喜欢称之为 scriptlets),并单独运行这些小的脚本,脚本运行后为其文件系统打一个快照 (Docker会自动执行此操作)。如果你发现一个scriptlet运行失败,你可以快速回退到上次的快照,然后再试一次。一旦你完成脚本的构建,并且 可以保证脚本能正常工作,那你就可以将它分配给其它主机。
回过头来再对比下,如果你没有使用快照功能了?当你辛辛苦苦等待了一个半小时后,脚本却构建失败了,我想除了少部分有耐心的人外,很多人是不想再来一次了,当然,你也会尽最大努力把系统恢复到失败前的状态,比如可以删除一个目录或运行make clean。
但是,我们可能没有真正地理解我们正在构建的组件。它可能有复杂的Makefile,它会把把文件放到文件系统中我们不知道的地方,唯一真正确定的途径是恢复到快照。
使用快照构建脚本的Docker
在本节中,我将介绍我是如何使用Docker实现GHC7.8.3 ARM交叉编译器的构建脚本。Docker非常适合做这件事,但并非完美。我做了很多看起来没用的或者不雅的事情,但都是必要的,这都是为了保证将开发脚本的总时间降到最低限度。构建脚本可以在这里找到。
用Dockerfile构建
Docker通过读取Dockerfile来构建镜像。Dockerfile会通过一些命令来具体指定应该执行哪些动作。具体使用说明可以参考这篇文章。在我的脚本中主要用到WORKDIR、ADD和RUN。ADD命令非常有用因为它可以让你在运行之前将外部文件添加到当前Docker镜像中然后转换成镜像的文件系统。你可以在这里看到很多scriptlets构成的构建脚本。
设计
1. 在RUN之前ADD scriptlets
如果你很早就将所有的scriptletsADD在Dockerfile,您可能会遇到以下问题:如果你的脚本构建失败,你回去修改scriptlet并再次运行docker build。但是你发现,Docker开始在首次加入scriptlets的地方构建!这样做会浪费了大量的时间并且违背了使用快照的目的。
出现这种情况的原因是由于Docker处理它的中间镜像(快照)的方式。当Docker通过Dockerfile构建镜像时,它会与中间镜像比较当前命令是否一致。然而,在ADD命令的情况下被装进镜像的文件里的内容也会被检查。如果相对于现有的中间镜像,文件已经改变,那么Docker也别无选择,只能从这点开始建立一个新的镜像。因为Docker不知道这些变化会不会影响到构建。
此外,使用RUN命令要注意,每次运行时它都会导致文件系统有不同的更改。在这种情况下,Docker会发现中间镜像并使用它,但是这将是错误的。RUN命令每次运行时会造成文件系统相同的改变。举个例子,我确保在我的scriptlets我总是下载了一个已知版本的文件与一个特定MD5校验。
对Docker 构建缓存更详细的解释可以在这里找到。
2.不要使用ENV命令来设置环境变量,请使用scriptlet。
它似乎看起来很有诱惑力:使用ENV命令来设置所有构建脚本需要的环境变量。但是,它不支持变量替换的方式,例如 ENV BASE=$HOME/base 将设置BASE的值为$HOME/base着很可能不是你想要的。
相反,我用ADD命令添加一个名为set-env.sh文件。此文件会包含在后续的scriptlet中:
THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $THIS_DIR/set-env-1.sh
如果你没有在第一时间获取set-env.sh会怎么样呢?它很早就被加入Dockerfile并不意味着修改它将会使随后的快照无效?
是的,这会有问题。在开发脚本时,我发现,我已经错过了在set-env.sh添加一个有用的环境变量。解决方案是创建一个新的文件set-env-1.sh包含:
THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $THIS_DIR/set-env.sh
if ! [ -e "$CONFIG_SUB_SRC/config.sub" ] ; then
CONFIG_SUB_SRC=${CONFIG_SUB_SRC:-$NCURSES_SRC}
fi
然后,在所有后续的scriptlets文件中包含了此文件。现在,我已经完成了构建脚本,我可以回去解决这个问题了,但是,在某种意义上,它会破坏最初的目标。我将不得不从头开始运行构建脚本看看这种变化是否能成功。
缺点
一个主要缺点是这种方法是,所构建的镜像尺寸是大于它实际需求的尺寸。在我的情况下尤其如此,因为我在最后删除了大量文件的。然而,这些文件都仍然存在于联合挂载文件系统的底层文件系统内,所以整个镜像是大于它实际需要的大小至少多余的是删除文件的大小。
然而,有一个变通。我没有公布此镜像到Docker Hub Registry。相反,我:
使用docker export导出内容为tar文件。
创建一个新的Dockerfile简单地添加了这个tar文件的内容。
产生尺寸尽可能小的镜像。
结论
这种方法的优点是双重的:
它使开发时间降至最低,不再做那些已经构建成功的子组件。你可以专注于那些失败的组件。
这非常便于维护构建脚本。构建可能会失败,但只要你搞定Dockerfiel,至少你不必再从头开始。
此外,正如我前面提到的Docker不仅使写这些构建脚本更加容易,有了合适的工具同样可以在任何提供快照的文件系统实现。

G. docker 一键脚本安装

Docker 官方提供了便捷的安装脚本,通过脚本自动完成安装.官方社区版本安装脚本一共有三种版本.第一个版本是主分支的Docker CE, Edge 更新渠道,每月更新一次;第二个版本是候选版本的DockerCE, Test 更新渠道,提供候选功能,候选功能不一定出现在主分支的DockerCE中,第三个版本是实验性的Docker CE版本,Experimental 更新渠道, 提供实验性功能比Test 更新渠道更加激进.

然后执行 systemctl daemon-reload 重启 daemon, 以及重启Docker 进程 sudo systemctl restart docker, 然后查看 Docker 版本信息即可

H. 解决 Docker 数据卷挂载的文件权限问题

Docker 提供了数据卷 绑定挂载 的机制(volume bind mounts)来将主机上的文件 (file) 或者目录 (directory) 挂载进容器 (container)。也就是 docker run 命令中熟知的 -v 参数。根据 Docker 官方文档,绑定挂载一般适合于 三种场景 :

但是实际使用时,会遇到文件权限问题:

譬如执行如下命令创建一个容器,挂载当前目录到容器内,并在容器内向主机当前目录创建 tmp.txt:

主机当前目录出现了容器内创建的 tmp.txt,但是其权限、用户和组均是 root,其他用户不可写。

常见解决方法是可以通过 Docker 提供的 User 命令、 --user 参数 来指定容器内部的用户和组的 id,譬如:

可以看到输出,current_user 处会显示主机当前用户的名字,所以解决了主机用户对挂载的卷没有权限的问题。

user 参数的缺陷
使用 user 参数有一些缺陷,如果你进入容器内部的 terminal,会显示如下内容:

bash 的用户名会显示 I have no name!,这是因为我们通过 --user 参数指定了容器内部的用户 id,但该 id 不存在于容器内的 /etc/passwd 文件中。

除此之外,使用 user 参数仍然存在权限问题:

除了绑定挂载的主机路径之外的所有路径,对于容器内部的用户都没有写权限。
这也是不可接受的,因为容器运行过程中我们可能会进行一些临时文件的写入,这些临时文件我们并不想要写到主机的挂载目录,但除了挂载路径之外的任何路径容器都没有写入权限。

譬如我们在主机上创建 models 目录。

我们使用 Docker 挂载 models 目录,然而在 Docker 容器内部除了 models 文件夹都没有访问权限。

这可以通过增加挂载路径:

这样容器运行过程往 /project 写的临时文件都会出现在主机上。

可见, user 参数并不能解决所有问题。它存在两个问题:

我们需要一种手段,既可以像 user 参数一样在容器运行时可以将用户切换到和主机相同的用户,又希望 Docker 容器保留 root 用户,并给主机用户想要访问的目录授权(对特定目录 chown 、 chmod 等)。

Docker 官方文档对 Entrypoint 介绍时给出了 一种最佳实践 。

编写如下的 Dockerfile:

该 Dockerfile 中安装了一个 gosu 的工具,并设置了程序的 Entrypoint。由于 Docker 内使用 sudo 可能导致一些不可预知的 TTY 和信号转发问题,所以 Docker 官方推荐了使用 gosu 这个工具,用于保持容器在 root 用户下运行,并用 sudo 来切换到指定用户。

其中 docker-entrypoint.sh 内容如下:

可以看到 docker-entrypoint.sh 中创建了一个名为 user 的用户,该用户的 uid 由 docker run 的参数传入,这里利用了 linux 系统的一个特点,容器内外用户权限的记录和用户的名字无关,只和 uid 有关,因此容器内我们将用户命名为 user 没有影响。docker-entrypoint.sh 最后一行调用 gosu 来切换到 user 用户并执行 Dockerfile 中的用户命令。

有了如上两个脚本,我们构建镜像并执行:

运行容器时指定 LOCAL_USER_ID 参数:

可见不仅容器内往挂载目录 /project/models 写入的文件 model.txt 所有者是主机用户,而且在容器内往非挂载目录 /project/tmp.txt 写入文件也不会遇到权限问题。

Docker 运行时容器内默认使用 root 用户运行,但是我们不是总是想要用 root 用户,因为有时候我们希望容器计算产生一些文件,并通过 volume 的绑定挂载在主机上获取。特别是我们用 jenkins 等工具写一些持续集成的脚本时候。容器内用 root 用户运行会导致产生的文件也是 root 用户的,主机上没有读取权限。因此我们需要让容器在运行的时候切换到主机上的用户。

Docker 对于这种情况仍然没有提供足够便利的基础设施,我们采用了 Docker 官方目前推荐的一个方式,通过编写一个 docker-entrypoint.sh 脚本作为 Dockerfile 的 Entrypoint,脚本中创建和主机上相同 uid 的用户,并通过 gosu 工具切换到该用户执行命令。 uid 需要在 docker run 阶段通过参数传入。我们在脚本中设置了缺省 uid ,上面的脚本随机选择了一个 9001,注意要将该缺省值避免设置成和 Docker 镜像中存在的用户冲突的 uid。

参考链接:

I. dockerfile是什么类型文件

Dockerfile是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。它们简化了从头到尾的流程并极大的简化了部署工作。Dockerfile从FROM命令开始,紧接着跟随者各种方法,命令和参数。其产出为一个新的可以用于创建容器的镜像。

#
#VERSION2-EDITION1
#Author:docker_user
#Commandformat:Instruction[arguments/command]..

#1、第一行必须指定基础镜像信息
FROMubuntu

#2、维护者信息
[email protected]

#3、镜像操作指令
RUNecho"debhttp://archive.ubuntu.com/ubuntu/raringmainuniverse">>/etc/apt/sources.list
RUNapt-getupdate&&apt-getinstall-ynginx
RUNecho" daemonoff;">>/etc/nginx/nginx.conf

#4、容器启动执行指令
CMD/usr/sbin/nginx

Dockerfile 分为四部分:基础镜像信息、维护者信息、镜像操作指令、容器启动执行指令。
一开始必须要指明所基于的镜像名称,接下来一般会说明维护者信息。
后面则是镜像操作指令,例如 RUN 指令。RUN 指令将对镜像执行跟随的指令。每执行一条RUN 指令,镜像添加新的一层,并提交
最后是 CMD 指令,来指明运行容器时的操作命令。

FROM 指令:格式: FROM <images> 或者 FROM<image>:<tag>。第一条指令必须是 FROM 指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个 FROM 指令。
MAINTAINER 指令:指定维护者信息。
RUN 指令:格式:RUN <command> 或者 RUN ["executable","param1","param2"]

另外通过直接下载程序镜像(Nginx)也可以创建一个容器,并将容器运行起来。

(1) 从中央仓库下载镜像:docker pull nginx:1.9
(2) docker run 命令启动容器,docker run -d -p 8080:80 nginx:1.9,把容器内的nginx的80端口,映射到当前服务器(Centos系统的ip地址)的8080端口,我当前服务器的ip是192.168.1.10,这样在浏览器输入192.168.1.10:8080/,发现nginx已启动。
(3) 再启动多一个容器,docker run -d -p 8085:80 nginx:1.9,浏览器输入http:/192.168.1.10:8085/,就可以看到另外一个nginx已启动。

J. 项目构建--Gradle--Docker打包(五)

如果添加了 application 插件的话,默认 gradle-docker 插件会添加一个 distDocker 的 gradle task,用来构建一个 包含所有程序文件 的 docker 镜像。

配置镜像名称和版本号

其中镜像的 tag 默认的构成为:项目组/应用名称:版本号

project.group:标准的 gradle 属性,如果不进行定义,插件默认会 省略 ${project.group} 这个属性。
applicationName:应用被容器化时的 名称。
tagVersion:可选属性,会作为镜像的 标签。默认值为 project.version,如果未指定 project.version,则使用 latest 作为标记。
配置docker构建基础信息:

其中,baseImage 相当于 Dockerfile 中声明的 FROM。声明了在 构建镜像 是基于的 Image,maintainer 相当于 MAINTAINER ,声明了 镜像作者。如果声明了 registry 地址,插件在 镜像射生成后 可以自动 push 到该地址。其他的配置还包括 docker hub 的 地址、用户名 和 密码。

taskBuilder 的任务配置:

构建完成以后,项目根目录的 build/docker 文件夹下面会出现 Dockerfile 和 spring-boot-gradle-for-docker-1.0.jar 文件。其中,以上的 task 等同于以下的 Dockerfile。

如果觉的在 task 中编写 Dockerfile 替换脚本 非常别扭,也可以直接在 task 中指定 Dockfile 的 文件路径,直接使用已有的文件来生成镜像:

通过 file() 指定 task 使用位于 项目根目录 的 Dockerfile 来生产镜像。

gradle 首先会运行 本地测试,然后进行项目打包,进一步根据 docker-gradle 插件进行镜像构建。
等待出现 BUILD SUCCESSFUL 就表明任务运行成功。可以观察到镜像的名称为:

运行 docker images 查看本地镜像,进一步验证镜像构建成功。

在工程根目录下新建Dockerfile文件,内容如下:

热点内容
c语言阶乘和 发布:2025-05-11 22:08:26 浏览:352
参展脚本 发布:2025-05-11 21:58:39 浏览:332
控制压缩类 发布:2025-05-11 21:50:59 浏览:899
c语言ba7aaa 发布:2025-05-11 21:36:25 浏览:989
九阴免费脚本 发布:2025-05-11 21:16:23 浏览:70
sqlserver存储过程递归 发布:2025-05-11 21:03:00 浏览:979
ios更新数据库 发布:2025-05-11 20:51:42 浏览:670
python开发培训哪家好 发布:2025-05-11 20:26:47 浏览:46
易语言配置怎么取 发布:2025-05-11 20:18:23 浏览:366
无法初始化程序配置怎么解决 发布:2025-05-11 20:18:22 浏览:15