02 . DockerFile构建镜像和Docker仓库

Posted lonelyxmas

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了02 . DockerFile构建镜像和Docker仓库相关的知识,希望对你有一定的参考价值。

原文:02 . DockerFile构建镜像和Docker仓库

1|0为什么用DockerFile

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

说dockerfile之前我们先说一下dockercommit

1|1利用commit理解镜像构成

注意: docker commit 命令除了学习之外,还有一些特殊的应用场合,比如被入侵后保存现 场等。但是,不要使用 docker commit 定制镜像,定制镜像应该使用 Dockerfile 来完成

镜像是容器的基础,每次执行 docker run 的时候都会指定哪个镜像作为容器运行的基础。

我们之前所使用的镜像都是docker hub等网站上的,直接使用这些镜像可以满足一定的需求,而当这些镜像无法直接满足需求时候,我们需要定制这些镜像.之前有说过,镜像是多层存储,每一层是在前一层的基础上进行的修改,而容器也是多层存储,是在以镜像为基础层,在其基础上加一层作为容器运行时的存储层.

1|2定制一个Web服务器
docker pull daocloud.io/library/nginx docker run --name webserver -d -p 80:80 daocloud.io/library/nginx # 我们访问这个web服务,会看到nginx的默认欢迎界面,假如我不喜欢这个界面,想看到欢迎docker的文字,可以exec curl 119.3.255.91 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> docker exec -it webserver bash root@6e63ab0d5109:/# echo ‘<h1>Hello,Docker!</h1>‘> /usr/share/nginx/html/index.html root@6e63ab0d5109:/# exit exit # 我们在访问时候就发现内容改变了 curl 119.3.255.91 <h1>Hello,Docker!</h1> # 我们修改了容器的文件,就是改动了容器的存储层,我们可以通过docker diff命令看到具体变动 docker diff webserver C /root A /root/.bash_history C /run A /run/nginx.pid C /var C /var/cache C /var/cache/nginx A /var/cache/nginx/fastcgi_temp A /var/cache/nginx/proxy_temp A /var/cache/nginx/scgi_temp A /var/cache/nginx/uwsgi_temp A /var/cache/nginx/client_temp C /usr C /usr/share C /usr/share/nginx C /usr/share/nginx/html C /usr/share/nginx/html/index.html

现在我们定制好了变化,我们希望将其保存下来形成镜像.

要知道,当我们运行一个容器的时候(如果不使用卷的话),我们做的任何文件修改都会被 记录于容器存储层里。而 Docker 提供了一个 docker commit 命令,可以将容器的存储层保 存下来成为镜像。换句话说,就是在原有镜像的基础上,再叠加上容器的存储层,并构成新 的镜像。以后我们运行这个新镜像的时候,就会拥有原有容器最后的文件变化(类似于虚拟机的快照)。

docker commit 的语法格式为: docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]] # 我们可以用下面的命令将容器保存为镜像 docker commit -a="youmen <18621048481@163.com>" -m="edited nginx Default page" webserver nginx:v2 * -m 提交的描述信息 * -a 指定镜像作者 * webserver为你要给那个容器做成镜像的那个容器名字或者ID * nginx:v2是形成的新镜像名 # 接下来我们基于这个创建好的新镜像再启动一个容器. docker run --name web2 -d -p 81:80 nginx:v2 curl `cat ip.txt`:81 <h1>Hello,Docker!</h1> # 就这样,我们完成了一次基于容器构建定制镜像的操作.
1|3慎用docker commit

使用 docker commit 命令虽然可以比较直观的帮助理解镜像分层存储的概念,但是实际环境 中并不会这样使用。

首先,如果仔细观察之前的 docker diff webserver 的结果,你会发现除了真正想要修改的 /usr/share/nginx/html/index.html 文件外,由于命令的执行,还有很多文件被改动或添加 了。这还仅仅是最简单的操作,如果是安装软件包、编译构建,那会有大量的无关内容被添 加进来,如果不小心清理,将会导致镜像极为臃肿。

此外,使用 docker commit 意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为黑 箱镜像,换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根 本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体在操作的。虽 然 docker diff 或许可以告诉得到一些线索,但是远远不到可以确保生成一致镜像的地步。 这种黑箱镜像的维护工作是非常痛苦的。

而且,回顾之前提及的镜像所使用的分层存储的概念,除当前层外,之前的每一层都是不会 发生改变的,换句话说,任何修改的结果仅仅是在当前层进行标记、添加、修改,而不会改 动上一层。如果使用 docker commit 制作镜像,以及后期修改的话,每一次修改都会让镜像 更加臃肿一次,所删除的上一层的东西并不会丢失,会一直如影随形的跟着这个镜像,即使 根本无法访问到。这会让镜像更加臃肿.

2|0使用Dockerfile定制镜像

从刚才的 docker commit 的学习中,我们可以了解到,镜像的定制实际上就是定制每一层所 添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚 本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问 题、体积的问题就都会解决。这个脚本就是 Dockerfile。

Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层, 因此每一条指令的内容,就是描述该层应当如何构建。

还以之前定制 nginx 镜像为例,这次我们使用 Dockerfile 来定制。

在一个空白目录中,建立一个文本文件,并命名为 Dockerfile :

cat DockerFile mkdir mynginx cd mynginx vim Dockerfile FROM nginx RUN echo ‘<h1>Hello, Docker!</h1>‘ > /usr/share/nginx/html/index.html
2|1FROM指定基础镜像

FROM为指定基础镜像,我们定制镜像,肯定要以一个镜像为基础,在其上做定制,而FROM就是指定基础镜像,因此一个Dockerfile中FROM是必备的命令,并且必须是第一条指令.

在Docker Store上有非常多高质量的官方镜像,有可以直接拿来使用的服务类镜像,如nginx,redis,mysql,mongo,tomcat等,也有方便开发、构建、运行各种语言的镜像,如node,openjdk,python,ruby,golang等,可以在其中寻找一个最符合我们的镜像为基础镜像进行定制.

如果还没有找到对应服务的镜像,官方镜像中提供了一些更为基础的操作系统镜像,如ubuntu,debian,centos,fedora,alpine等,这些操作系统的软件库为我们提供了更广阔的扩展空间.

除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为 scratch 。这个镜像 是虚拟的概念,并不实际存在,它表示一个空白的镜像。

如果你以 scratch 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作 为镜像第一层开始存在。 不以任何系统为基础,直接将可执行文件复制进镜像的做法并不罕见,比如 swarm 、 coreos/etcd 。对于 Linux 下静态编译的程序来说,并不需要有操作系统提供运行时 支持,所需的一切库都已经在可执行文件里了,因此直接 FROM scratch 会让镜像体积更加小 巧。使用 Go 语言 开发的应用很多会使用这种方式来制作镜像,这也是为什么有人认为 Go 是特别适合容器微服务架构的语言的原因之一。

2|2RUN 执行命令

RUN 指令是用来执行命令行命令的。由于命令行的强大能力, RUN 指令在定制镜像时是最 常用的指令之一。其格式有两种:

shell 格式: RUN <命令> ,就像直接在命令行中输入的命令一样。刚才写的 Dockerfile 中 的 RUN 指令就是这种格式。

RUN echo ‘<h1>Hello, Docker!</h1>‘ > /usr/share/nginx/html/index.html

exec 格式: RUN ["可执行文件", "参数1", "参数2"] ,这更像是函数调用中的格式。 既然 RUN 就像 Shell 脚本一样可以执行命令,那么我们是否就可以像 Shell 脚本一样把每个 命令对应一个 RUN 呢?比如这样:

cat Dockerfile FROM debian:jessie RUN apt-get update RUN apt-get install -y gcc libc6-dev make RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" RUN mkdir -p /usr/src/redis RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 RUN make -C /usr/src/redis RUN make -C /usr/src/redis install

之前说过,Dockerfile 中每一个指令都会建立一层, RUN 也不例外。每一个 RUN 的行为, 就和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束 后, commit 这一层的修改,构成新的镜像。

而上面的这种写法,创建了 7 层镜像。这是完全没有意义的,而且很多运行时不需要的东 西,都被装进了镜像里,比如编译环境、更新的软件包等等。结果就是产生非常臃肿、非常 多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。 这是很多初学 Docker 的人常 犯的一个错误。

Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过 127 层。因此上面Dockerfile可以这样写:

cat DockerFile FROM debian:jessie RUN buildDeps=‘gcc libc6-dev make‘ && apt-get update && apt-get install -y $buildDeps && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" && mkdir -p /usr/src/redis && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 && make -C /usr/src/redis && make -C /usr/src/redis install && rm -rf /var/lib/apt/lists/* && rm redis.tar.gz && rm -r /usr/src/redis && apt-get purge -y --auto-remove $buildDeps

首先,之前所有的命令只有一个目的,就是编译、安装 redis 可执行文件。因此没有必要建立 很多层,这只是一层的事情。因此,这里没有使用很多个 RUN 对一一对应不同的命令,而是 仅仅使用一个 RUN 指令,并使用 && 将各个所需命令串联起来。将之前的 7 层,简化为了 1 层。在撰写 Dockerfile 的时候,要经常提醒自己,这并不是在写 Shell 脚本,而是在定义每 一层该如何构建。

并且,这里为了格式化还进行了换行。Dockerfile 支持 Shell 类的行尾添加 的命令换行方 式,以及行首 # 进行注释的格式。良好的格式,比如换行、缩进、注释等,会让维护、排障 更为容易,这是一个比较好的习惯。

此外,还可以看到这一组命令的最后添加了清理工作的命令,删除了为了编译构建所需要的 软件,清理了所有下载、展开的文件,并且还清理了 apt 缓存文件。这是很重要的一步,我 们之前说过,镜像是多层存储,每一层的东西并不会在下一层被删除,会一直跟随着镜像。 因此镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清 理掉。

很多人初学 Docker 制作出了很臃肿的镜像的原因之一,就是忘记了每一层构建的最后一定要 清理掉无关文件。

2|3构建镜像

在之前Dockerfile文件所在目录执行

cat DockerFile mkdir mynginx cd mynginx # 我们继续编辑一下DockerFile vim DockerFile FROM nginx RUN echo ‘<h1>Hello, Docker!</h1>‘ > /usr/share/nginx/html/index.html docker build -t nginx:v3 . # 最后的.表示本文执行的上下文路径 Sending build context to Docker daemon 2.048kB Step 1/2 : FROM nginx ---> 231d40e811cd Step 2/2 : RUN echo ‘<h1>Hello, Docker!</h1>‘ > /usr/share/nginx/html/index.html ---> Running in 3a439666c4da Removing intermediate container 3a439666c4da ---> 78990dc4a6a6 Successfully built 78990dc4a6a6 Successfully tagged nginx:v3

从命令的输出结果中,我们可以清晰的看到镜像的构建过程。在 Step 2 中,如同我们之前 所说的那样, RUN 指令启动了一个容器231d40e811cd,执行了所要求的命令,并最后提交 了这一层 3a439666c4da ,随后删除了所用到的这个容器78990dc4a6a6。

docker build [选项] <上下文路径/URL/->

构建成功后我们可以跟nginx:v2那样运行这个镜像,结果一样.

这只是默认行为,实际上 Dockerfile 的文件名并不要求必须为 Dockerfile ,而且并不要求 必须位于上下文目录中,比如可以用 -f ../Dockerfile.php 参数指定某个文件作为 Dockerfile

2|4上下文路径

是指在docker构建镜像,有时候想要使用本机的文件(比如复制),docker build命令知道这个路径后,会将这个路径下所有内容打包.

由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。

如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。

注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。

2|5Docker build的用法

直接用git repo 进行构建

yum -y install git docker build https://github.com/twang2218/gitlab-ce-zh.git:8.14 docker build https://github.com/twang2218/gitlab-ce-zh.git#:8.14 Sending build context to Docker daemon 2.048 kB Step 1 : FROM gitlab/gitlab-ce:8.14.0-ce.0 8.14.0-ce.0: Pulling from gitlab/gitlab-ce

这行命令指定了构建所需的Git repo,并且指定默认的master分支,构建目录为/8.14/,然后Docker就会自己去git clone这个项目,切换到指定分支,并进入到指定目录后开始构建.

用给定的tar压缩包构建

docker build http://server/context.tar.gz # 如果所给出的 URL 不是个 Git repo,而是个 tar 压缩包,那么 Docker 引擎会下载这个包, # 并自动解压缩,以其作为上下文,开始构建。

从标准输入中读取Dockerfile进行构建

docker build - < Dockerfile or cat Dockerfile | docker build -

如果标准输入传入的是文本文件,则将其视为 Dockerfile ,并开始构建。这种形式由于直接 从标准输入中读取 Dockerfile 的内容,它没有上下文,因此不可以像其他方法那样可以将本 地文件 COPY 进镜像之类的事情。

从标准输入中读取上下文压缩包进行构建

docker build - < context.tar.gz # 如果发现标准输入的文件格式是gzip、bzip2、以及xz的话,将会使其为上下文压缩包,直接将其展开, # 将里面视为上下文,并开始构建.

3|0Dockerfile指令详解

3|1FROM 和 RUN 指令的作用

FROM:定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。

RUN:用于执行后面跟着的命令行命令。有以下俩种格式

shell格式

RUN <命令行命令> # <命令行命令> 等同于,在终端操作的 shell 命令。

exec格式

RUN ["可执行文件", "参数1", "参数2"] # 例如: # RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

注意: Dockerfile的指令是每执行一次都会在docker上新建一层,所以过多无意义的层,会造成镜像膨胀过大,上面提到过,可以用&&符号链接命令,这样执行后,只会创建一层镜像

3|2COPY复制文件
# 格式: # COPY <源路径>...<目标路径> COPY ["<源路径1>",..."<目标路径>"] # 和RUN指令一样,也有两种格式,一种类似于命令行,一种类似于函数调用. COPY指令将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径> 位置,比如. COPY package.json /usr/src/app/ # <源路径> 可以是多个,甚至可以是通配符,其通配符规则要满足Go的filepath.Match规则,如: COPY hom* /mydir/ COPY hom?.txt /mydir/ # <目标路径> 可以是容器内的绝对路径,也可以是相对于工作目录的相对路径.工作目录可以 用 WORKDIR 指令来指定). # 目标路径不需要事先创建,如果目录不存在会在复制文件前先行 创建缺失目录 # 此外,还需要注意一点,使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执 行权限、文件变更时间等. # 这个特性对于镜像定制很有用。特别是构建相关文件都在使用 Git 进行管理的时候。
3|3ADD

ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。

ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

3|4CMD

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

  • CMD 在docker run 时运行。
  • RUN 是在 docker build。

作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

格式:

CMD <shell 命令> CMD ["<可执行文件或命令>","<param1>","<param2>",...] CMD ["<param1>","<param2>",...] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
3|5ENTRYPOINT

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

但是, 如果运行 docker run 时使用了 --entrypoint 选项,此选项的参数可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序。

优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

格式:

ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。

示例:

假设已通过 Dockerfile 构建了 nginx:test 镜像:

FROM nginx ENTRYPOINT ["nginx", "-c"] # 定参 CMD ["/etc/nginx/nginx.conf"] # 变参

不传参运行

docker run nginx:test # 容器内会默认运行以下命令,启动主进程 nginx -c etc/nginx/nginx.conf

传参运行

docker run nginx:test -c /etc/nginx/new.conf # 容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)
3|6ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

格式:

ENV <key> <value> ENV <key1>=<value1> <key2>=<value2>...

以下示例设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:

ENV NODE_VERSION 7.2.0 RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"
3|7ARG

构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。

格式:

ARG <参数名>[=<默认值>]
3|8VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

作用:

  • 避免重要的数据,因容器重启而丢失,这是非常致命的。
  • 避免容器不断变大。

格式

VOLUME ["<路径1>", "<路径2>"...] VOLUME <路径> # 在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。
3|9EXPOSE

仅仅只是声明端口。

作用:

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
  • 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

格式:

EXPOSE <端口1> [<端口2>...]
3|10WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。

docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

格式:

WORKDIR <工作目录路径>
3|11USER

用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。

格式:

USER <用户名>[:<用户组>]
3|12HEALTHCHECK

用于指定某个程序或者指令来监控 docker 容器服务的运行状态。

格式:

# HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令 # HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令 # HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。
3|13ONBUILD

用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这是执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。

格式

ONBUILD <其它指令>

4|0Docker仓库

5|0访问仓库

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

一个容易混淆的概念是注册服务器( Registry )。实际上注册服务器是管理仓库的具体服务 器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像。从这方面来说,仓库可以 被认为是一个具体的项目或目录。例如对于仓库地址 dl.dockerpool.com/ubuntu 来 说, dl.dockerpool.com 是注册服务器地址, Ubuntu 是仓库名。

大部分时候,并不需要这两者的概念.

6|0Docker Hub

目前Docker官方维护了一个公共仓库Docker Hub,其中包括了数量超过15000的镜像,大部分需求都可以通过在Docker Hub中直接下载镜像来实现.

注册,可以直接在https://cloud.docker.com免费注册一个Docker Hub账号.

登陆

可以通过执行docker login 命令交互式的输入用户名及密码来完成命令行界面登陆Docker Hub。docker logout退出登陆.

6|1拉取镜像

可以通过docker search命令来查找官方仓库中的镜像,并利用docker pull命令将他下载到本地.

docker search centos NAME DESCRIPTION STARS OFFICIAL AUTOMATED centos The official build of CentOS. 5717 [OK] ansible/centos7-ansible Ansible on Centos7 126 [OK] jdeathe/centos-ssh OpenSSH / Supervisor / EPEL/IUS/SCL Repos - … 114 [OK] consol/centos-xfce-vnc Centos container with "headless" VNC session… 101 [OK]

可以看到返回了很多包含关键字的镜像,其中包括镜像名字、描述、收藏数(表示该镜像的受关注程度),是否官方创建、是否自动创建.

根据是否是官方提供,可将镜像资源分为两类.

一种是类似centos这样的镜像,被称为基础镜像或根镜像,这些基础镜像由Docker公司创建、验证、支持、提供。这样的镜像往往使用单个单词作为名字.

还有一种类型,比如tianon/centos镜像,他是由Docker的用户创建并维护的,往往带有用户名称前缀,可以通过前缀username/来指定某个用户提供的镜像,比如tianon用户.

另外,在查找的时候可以通过--filter=stars=N参数可以显示收藏数量为N以上的镜像.

6|2推送镜像

用户可以在登陆后通过docker push命令将自己的镜像推送到Docker Hub。

以下命令的flyingdreams请替换为你的Docker账号用户名.

docker login # 登陆自己的账号 docker tag nginx:v2 flyingdreams/nginx:v2 docker push flyingdreams/nginx:v2

技术图片

6|3自动创建

自动创建(Automated Builds)功能对于需要经常升级镜像内程序来说,十分方便.

有时候,用户创建了镜像,安装了某个软件,如果程序发布新版本则需要手动更新镜像.

而自动创建允许用户Docker Hub指定跟踪一个目标网站(目前支持GitHub或BitBucket)上的项目,一旦项目发生新的提交或者创建新的标签(tag),Docker Hub会自动构建镜像并推送到Docker Hub中.

要配置自动创建,包括如下的步骤:

# 1. 创建并登陆Docker Hub,以及目标网站: # 2. 在目标网站中连接账户到Docker Hub; # 3. 在Docker Hub中配置一个自动连接: # 4. 选取一个目标网站中的项目(需要含Dockerfile)和分支 # 5. 指定Dockerfile的位置,并提交创建. # 之后,可以在Docker Hub的自动创建页面中跟踪每次创建的状态.

7|0私有仓库docker-registry

有时候使用Docker Hub这样的公共仓库可能不安全,用户可以创建一个本地仓库供私人使用.

通过官方提供的私有仓库镜像registry来搭建私有仓库。通过 humpback 快速搭建轻量级的Docker容器云管理平台

此外还有像Harbor,rancher等私有仓库。

7|1安装运行docker-registry
# 自定义存储位置$HOME,一般是root docker run -d -p 5000:5000 --restart=always --name registry -v $HOME/_docker/registry:/var/lib/registry registry:2.6 # 从官方仓库拉去一个镜像 docker pull nginx docker tag nginx:latest 47.92.24.137:5000/test_nginx:latest # 在推送到的时候报错误,默认是使用`https`提交,这个搭建的默认使用的是 `http`,解决方法两个: # 创建一个https映射 # 将仓库地址加入到不安全的仓库列表中 # 我们使用第二种方法,加入到不安全的仓库列表中,修改docker配置文件 # `vi /etc/docker/daemon.json` 添加 `insecure-registries`配置信息 docker push 47.92.24.137:5000/test_nginx:latest The push refers to repository [47.92.24.137:5000/test_nginx] Get https://47.92.24.137:5000/v2/: http: server gave HTTP response to HTTPS client cat /etc/docker/daemon.json { "insecure-registries":[ "47.92.24.137:5000" ] } systemctl stop docker systemctl daemon-reload systemctl start docker # 推送到私有仓库中 docker push 47.92.24.137:5000/test_nginx:latest ls /root/_docker/registry/docker/registry/v2/repositories/test_nginx/ _layers _manifests _uploads

8|0安装运行harbor(http方式)

Harbor 可帮助用户迅速搭建企业级的 Registry 服务, 它提供了管理图形界面, 基于角色的访问控制 ( Role Based Access Control), 镜像远程复制 (同步), AD/LDAP 集成, 以及审计日志等企业用户需求的功能, 同时还原生支持中文, 深受中国用户的喜爱;

8|1安装harbor

VMware 公司开源了企业级 Registry 项目, 其的目标是帮助用户迅速搭建一个企业级的 Docker registry 服务。

由于 Harbor 是基于 Docker Registry V2 版本,所以 docker 版本必须 >=1.10.0 docker-compose >=1.6.0

下载最新版 Docker Compose
curl -L "https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

下载最新版Docker Harbor
wget https://github.com/goharbor/harbor/releases/download/v1.10.0-rc1/harbor-offline-installer-v1.10.0-rc1.tgz

# 对二进制文件应用可执行权限: sudo chmod +x /usr/local/bin/docker-compose # 测试是否安装成功 docker-compose --version # 按照上面给的docker harbor地址,下载离线安装包 tar xvf harbor-offline-installer-v1.8.1.tgz -C /usr/local/ vim /usr/local/harbor/harbor.yml hostname: 47.92.24.137 # 运行安装脚本 ./install.sh [Step 0]: checking installation environment ... Note: docker version: 19.03.4 Note: docker-compose version: 1.22.0 [Step 1]: loading Harbor images ... Loaded image: goharbor/harbor-core:v1.8.1 Loaded image: goharbor/harbor-registryctl:v1.8.1 Loaded image: goharbor/redis-photon:v1.8.1 Loaded image: goharbor/notary-server-photon:v0.6.1-v1.8.1 Loaded image: goharbor/chartmuseum-photon:v0.8.1-v1.8.1 Loaded image: goharbor/harbor-db:v1.8.1 Loaded image: goharbor/harbor-jobservice:v1.8.1 Loaded image: goharbor/nginx-photon:v1.8.1 Loaded image: goharbor/registry-photon:v2.7.1-patch-2819-v1.8.1 Loaded image: goharbor/harbor-migrator:v1.8.1 Loaded image: goharbor/prepare:v1.8.1 Loaded image: goharbor/harbor-portal:v1.8.1 Loaded image: goharbor/harbor-log:v1.8.1 Loaded image: goharbor/notary-signer-photon:v0.6.1-v1.8.1 Loaded image: goharbor/clair-photon:v2.0.8-v1.8.1 [Step 2]: preparing environment ... prepare base dir is set to /usr/local/harbor Generated configuration file: /config/log/logrotate.conf Generated configuration file: /config/nginx/nginx.conf Generated configuration file: /config/core/env Generated configuration file: /config/core/app.conf Generated configuration file: /config/registry/config.yml Generated configuration file: /config/registryctl/env Generated configuration file: /config/db/env Generated configuration file: /config/jobservice/env Generated configuration file: /config/jobservice/config.yml Generated and saved secret to file: /secret/keys/secretkey Generated certificate, key file:/secret/core/private_key.pem, cert file:/secret/registry/root.crt Generated configuration file: /compose_location/docker-compose.yml Clean up the input dir [Step 3]: starting Harbor ... ? ----Harbor has been installed and started successfully.---- Now you should be able to visit the admin portal at http://47.92.24.137. For more details, please visit https://github.com/goharbor/harbor

接下来我们可以直接浏览器访问配置文件定义的IP或者域名加端口

技术图片

技术图片

8|2修改harbor端口
# 因为harbor默认端口是80,而大多数时候是不希望使用80端口,修改方法如下 # vim harbor.yml # 找到port选项修改端口,然后执行./install 就会使用配置文件端口 # 还有一种情况就是更改已有harbor的配置 vim docker-compose.yml dns_search: . ports: - 99:80 auth: token: issuer: harbor-token-issuer realm: http://47.92.24.137:99/service/token rootcertbundle: /etc/registry/root.crt service: harbor-registry docker-compose down -v docker-compose up -d

技术图片

8|3使用harbor

为了体现出效果,建议使用非harbor的另一台机器

# 镜像推送 docker login 47.92.24.137:99 -u admin -p youmen vim /etc/docker/daemon.jsonyml { "insecure-registries":["47.92.24.137"] } systemctl daemon-reload systemctl restart docker # 因为docker默认使用的是https协议,而搭建harbor是http提供服务的, # 所以要配置可信任,或者强制docker login和docker push 走http的80端口,而不是443端口. docker tag nginx:latest 47.92.24.137:99/library/nginx:latest docker push 47.92.24.137:99/library/nginx:latest

技术图片

9|0安装harbor(https方式)

9|1DNS服务器安装dnsmasq
yum -y install dnsmasq mkdir -p /data/ssl && cd /data/ssl vim harbor.cfg hostname = harbor.youmen.com ui_url_protocol = https db_password = root123 harbor_admin_password = baiyongjie ssl_cert = /usr/local/harbor/cert/harbor.youmen.com.crt   ssl_cert_key = /usr/local/harbor/cert/harbor.youmen.com.key # grep -Ev ‘#|^$‘ harbor.yml hostname: harbor.youmen.com # 本机外网IP或域名,该地址供用户通过UI进行访问,不要使用127.0.0.1 https: # 用户访问私仓时使用的协议,默认时http,配置成https port: 443 # https使用的端口 certificate: /usr/local/harbor/cert/harbor.youmen.com.crt # 设置证书文件路径 private_key: /usr/local/harbor/cert/harbor.youmen.com.key # 设置证书密钥文件路径 harbor_admin_password: youmen # harbor的管理员账户密码 database: password: root123 # 指定mysql数据库管理员密码 data_volume: /data # image存储目录 clair: updaters_interval: 12 http_proxy: https_proxy: no_proxy: 127.0.0.1,localhost,core,registry jobservice: max_job_workers: 10 chart: absolute_url: disabled log: level: info rotate_count: 50 rotate_size: 200M location: /var/log/harbor _version: 1.8.0

生成harbor证书

mkdir /usr/local/harbor/cert/ cd /usr/local/harbor/cert/ #生成根证书 openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 3650 -out ca.crt -subj "/C=CN/L=Shanghai/O=harbor/CN=harbor-registry" #生成一个证书签名, 设置访问域名为 harbor.baiyongjie.com openssl req -newkey rsa:4096 -nodes -sha256 -keyout harbor.youmen.com.key -out server.csr -subj "/C=CN/L=Shanghai/O=harbor/CN=harbor.youmen.com" #生成主机证书 openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out harbor.youmen.com.crt # 接下来执行自动安装脚本即可. 添加本地解析到hosts #echo "192.168.1.155 harbor.baiyongjie.com" >> /etc/hosts #cd /usr/local/harbor # ./install.sh

官方建议不要在Harbor上启用https,而是将Harbor放置到一个SLB的后边,配置SLB的端口转发进行访问,或者再装一个Nginx,进行Nginx的端口转发.

如果想做一个HA方案的话,可以按照如下方式构建一个(主从模式个人感觉很不靠谱

负载均衡同时还要承担检查的任务,而Redis用于数据的缓存和消息队列的实现,Mysql存储用户信息和仓库信息,云存储用来存储Docker镜像.


__EOF__

技术图片
本文作者讨厌自己明明不甘平凡,却又不好好努力.周常见
本文链接https://www.cnblogs.com/you-men/p/13121835.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!








以上是关于02 . DockerFile构建镜像和Docker仓库的主要内容,如果未能解决你的问题,请参考以下文章

Docke--Dockerfile实践

Docker-dockerfile文件

Docker-dockerfile文件

docker之构建镜像

Docker 入门:Dockerfile

Docker 入门:Dockerfile