日志

容器技术之Docker镜像

 来源    2020-05-23    0  

  前文我们聊了下docker的基础使用方法,大概介绍了下docker的架构,管理镜像、运行容器、管理容器的一些相关命令说明;回顾请参考https://www.cnblogs.com/qiuhom-1874/p/12933412.html;今天这边博客主要来聊docker的镜像的制作和分发,以及相关镜像的操作和说明;

  前面我们提到过docker最核心资源之一就是镜像,镜像就好比是我们的应用程序,要想运行它,前提是要拥有它,并把它装载操作系统上;而docker里的镜像就是把应用程序所依赖的库、文件、环境等打包在一起,组成一个静态的镜像文件;这样一来有了这个镜像,我们就可以把我们自己的应用程序在任何有docker环境的主机上运行成容器;这也是docker受欢迎的原因之一吧,解脱了程序员为其应用程序而苦恼;

  docker镜像包含了应用程序启动所需的文件系统以及内容,其目的就是为创建并启动为docker容器;那么docker的镜像到底是怎么构建的呢?我们来看看下面的图大概就会明白

  提示:docker镜像采用分层构建的机制,最低层为bootfs,该层的主要作用是用于系统引导的文件系统,包括bootloader和内核,容器启动完成后会被卸载以节省内存资源;在bootfs之上的是rootfs,该层主要表现为docker容器的根文件系统;传统模式中,系统启动之时,内核挂载rootfs时会首先将其挂载为只读模式,完成完整性自检后在将其重新挂载为读写模式;而docker中,rootfs有内核挂载为只读模式,而后通过联合挂载技术额外挂载一个可写成;如下图所示

  提示:位于下层的镜像我们称为父镜像,最底层的镜像称其为基础镜像;最上层为可写层,其下的所有层都是只读层;从上面的图我们也可以看到,只有镜像运行成容器以后才会有可写层的;也就是说可写层属于容器而不属于镜像;其实docker容器是共享下面镜像层的,只有启动为容器后,各自的可写层相互隔离;

  了解了docker的镜像构建方式后,我们在看看多个镜像怎么做到联合挂载的?

  联合挂载的技术要源于AUFS这个文件系统,该文件系统的全称是advanced multi-layered unification filesystem翻译过来就是高级多层统一文件系统;该文件主要作用是为Linux文件系统实现“联合挂载”;aufs的前身是unionfs,2006年由junjiro okajima开发;docker最初使用aufs作为容器文件系统层,它目前仍作为存储后端之一,aufs的竞争产品是overlayfs,后者自从3.18版本开始被合并到Linux内核;docker的分层镜像,除了aufs,docker还支持btrfs,devicemapper和vfs等,在ubuntu系统下,docker默认使用的aufs;而在早期centos7上用的是devicemapper;所以早期跑docker都跑在ubuntu上,原因之一是ubuntu的内核版本较新,能够很好的兼容aufs文件系统;现在我们在centos7上运行docker默认使用的是overlayfs2文件系统;如下所示

 

  提示:如果用运行docker建议backing filesystem 使用xfs文件系统,不要使用ext系列文件系统;

   了解了docker的文件系统后,在来说一下docker的镜像仓库

  docker启动容器时,docker 服务端会试图从本地获取相关镜像;本地镜像不存在时,将会从docker默认的镜像仓库中下载指定镜像并保持本地,然后再启动为容器;大致过程如下图所示

  提示:从上图可以了解到docker客户端和服务端的一个工作流程,客户端通过http协议向服务端发送指令,服务端首先从本地查找是否有对应版本的镜像,如果有就启动为容器,如果没有就会去默认的registry中下载对应版本的镜像到本地,然后在启动为容器;对于docker服务端和registry来讲他们都需要各自的存储设备驱动来存储镜像;registry是用于保存docker镜像,包括镜像的层次机构和元数据;用户可以自建registry,也可使用官方的docker hub;registry分类主要有Sponsor registry 第三方的registry,供客户和docker社区使用;mirror registry 第三方的registry,只让客户使用;vendor registry 由发布docker镜像的供应商提供的registry;private registry 通过设有防火墙和额外的安全层的私有实体提供的registry;

  registry主要包含了仓库和索引;所谓仓库就是由特定的docker镜像的所有迭代版本组成的镜像仓库;一个registry中可以存在多个repository,而对于repository来说可以分为顶层仓库和用户仓库,顶层仓库就是没有斜线分割的仓库,用户仓库是由用户名加斜线分割再加仓库名组成;每个仓库可以包含多个tag标签,每个标签对应一个镜像;所谓索引(index)主要用于维护用户帐号、镜像的校验以及公共命名空间的信息,相对于为registry提供一个完整用户认证等功能的检索接口;所以我们把registry理解为存放docker镜像仓库的仓库更为准确;docker registry中的镜像通常由开发人员制作,而后推送至公共或私有的仓库上保持,供其他人员使用;如下图所示

  了解了registry和repository的关系后,我们在来说说docker hub;docker hub 是docker的官方仓库,它主要有如下几种特性;

  1、image repositories,提供镜像仓库的功能

  2、autometed builds,提供自动编译功能,什么意思呢?它支持我们向上传一个构建docker镜像的源码文件,它可以根据这个源码文件自动生成docker 镜像;这个源码文件叫dockerfile 主要用于编写镜像的构建过程的指令文件;

  3、Webhooks,提供监控目标资源的变化实现根据目标监控对象上的资源变化而变化的一种机制;比如我们可以使用github和dockerhub联合起来,开发人员通过git向github提交代码(dockerfile),然后dockerhub就会一直盯着github上的资源,如果有变化,它就根据监控的资源变化而重新编译成一个镜像,类似这种功能;

  4、organizations,支持创建组的方式对镜像仓库的访问管理

  5、github and bitbucket integration,支持将github和bitbucket添加到你当前的docker 镜像工作流中;

  了解了以上内容,我们在dockerhub上去注册一帐号,就可以创建仓库去存放我们自己制作好的镜像了;注册帐号这里我就不多说了,我们来说一下怎样制作镜像和怎么把镜像推送到我们自己的仓库中去;

  基于现有镜像制作镜像

  1、拖镜像到本地

[root@node1 ~]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              7                   b5b4d78bc90c        2 weeks ago         203MB
nginx               stable-alpine       ab94f84cc474        4 weeks ago         21.3MB
[root@node1 ~]# docker image pull busybox:latest
latest: Pulling from library/busybox
d9cbbca60e5f: Pull complete 
Digest: sha256:836945da1f3afe2cfff376d379852bbb82e0237cb2925d53a13f53d6e8a8c48c
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest
[root@node1 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             latest              78096d0a5478        9 days ago          1.22MB
centos              7                   b5b4d78bc90c        2 weeks ago         203MB
nginx               stable-alpine       ab94f84cc474        4 weeks ago         21.3MB
[root@node1 ~]#

  2、运行busybox为容器

  提示:busybox容器默认提供的是一个模拟Linux很多命令的一个程序,本身没有跑任何进程;所以我们启动容器必须得用交互式终端才行,否则容器启动不起来;-it表示启动为交互式终端;

  3、创建httpd的网页文件

  提示:到此我们在容器内部的数据就准备好了。现在需要将我们修改后的数据保存下来制作成镜像分发给其他人使用;

  4、基于现有容器制造镜像

[root@node1 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             latest              78096d0a5478        9 days ago          1.22MB
centos              7                   b5b4d78bc90c        2 weeks ago         203MB
nginx               stable-alpine       ab94f84cc474        4 weeks ago         21.3MB
[root@node1 ~]# docker container commit --help

Usage:  docker container commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

Create a new image from a container's changes

Options:
  -a, --author string    Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
  -c, --change list      Apply Dockerfile instruction to the created image
  -m, --message string   Commit message
  -p, --pause            Pause container during commit (default true)
[root@node1 ~]# docker container commit -a "qiuhom <qiuhom@admin123.com>" -p -m "this is test image" -c 'CMD ["/bin/sh","-c","/bin/httpd -f -h /var/www/web/html"]' b1 linux1874/myimg:v0.1   
sha256:e408b1c6e04f0e5f5129989f35e6f613dec17d963770c4be8d6daa54343c5399
[root@node1 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
linux1874/myimg     v0.1                e408b1c6e04f        5 seconds ago       1.22MB
busybox             latest              78096d0a5478        9 days ago          1.22MB
centos              7                   b5b4d78bc90c        2 weeks ago         203MB
nginx               stable-alpine       ab94f84cc474        4 weeks ago         21.3MB
[root@node1 ~]#

  提示:-a表示指定作者信息,通常情况下作者信息是带邮箱地址的;-p 表示制作镜像时暂停容器,这样做主要是为了数据统一,预防制作过程中的数据增加;-m表示注解信息;-c表示指定容器内部运行的命令;从上面的结果看,我们在本地就可以看到我们制作的镜像;这里需要特别注意一点的时,在docker容器里运行的服务必须前台运行,如果后台运行会导致容器一启动就退出了,原因是容器内部本身就只有一个进程在跑,如果你后台运行,就没有进程在前台,所以docker会认为该容器已经宕机;其实我们可以理解为容器内部前台跑的程序是支撑整个容器为运行态的重要骨架;

  5、登录自己dockerhub帐号

[root@node1 ~]# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: linux1874    
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
[root@node1 ~]#

  6、推送镜像到dockerhub中我们自己的仓库中去

[root@node1 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
linux1874/myimg     v0.1                e408b1c6e04f        7 minutes ago       1.22MB
busybox             latest              78096d0a5478        9 days ago          1.22MB
centos              7                   b5b4d78bc90c        2 weeks ago         203MB
nginx               stable-alpine       ab94f84cc474        4 weeks ago         21.3MB
[root@node1 ~]# docker image push --help

Usage:  docker image push [OPTIONS] NAME[:TAG]

Push an image or a repository to a registry

Options:
      --disable-content-trust   Skip image signing (default true)
[root@node1 ~]# docker image push linux1874/myimg:v0.1
The push refers to repository [docker.io/linux1874/myimg]
4d567d38fed1: Pushed 
1079c30efc82: Mounted from library/busybox 
v0.1: digest: sha256:6c2f6b7a0df5ca0a46cd46d858e9fd564169471e6715c0155027ac77672508f6 size: 734
[root@node1 ~]#

  提示:制作的镜像打标签时,需要打成同仓库名一致的名称;到此我们就把我们制作好的镜像推送到我们的仓库中去了

  7、到dockerhub仓库中查看是否存在我们刚才制作好的镜像?

  提示:可以看到我们有一个叫v0.1的镜像;

  8、另外开启一主机,下载该镜像,看看是否能够启动为容器,并提供httpd服务呢?

[root@docker_node1 ~]# docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
wordpress           latest              c3fa1c8546fb        3 weeks ago         540MB
mysql               5.7                 f965319e89de        3 weeks ago         448MB
httpd               2.4.37-alpine       dfd436f9a5d8        17 months ago       91.8MB
[root@docker_node1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@docker_node1 ~]# docker image pull linux1874/myimg:v0.1
Error response from daemon: pull access denied for linux1874/myimg, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
[root@docker_node1 ~]# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: linux1874
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
[root@docker_node1 ~]# docker image pull linux1874/myimg:v0.1
v0.1: Pulling from linux1874/myimg
d9cbbca60e5f: Pull complete 
ab68b1a31f97: Pull complete 
Digest: sha256:6c2f6b7a0df5ca0a46cd46d858e9fd564169471e6715c0155027ac77672508f6
Status: Downloaded newer image for linux1874/myimg:v0.1
docker.io/linux1874/myimg:v0.1
[root@docker_node1 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
linux1874/myimg     v0.1                e408b1c6e04f        20 minutes ago      1.22MB
wordpress           latest              c3fa1c8546fb        3 weeks ago         540MB
mysql               5.7                 f965319e89de        3 weeks ago         448MB
httpd               2.4.37-alpine       dfd436f9a5d8        17 months ago       91.8MB
[root@docker_node1 ~]# docker run --name myweb1 -d linux1874/myimg:v0.1
5bd8e32089c0431399c9f81bbbdcf946817d3f8ab32ffc1caf072e73ed9ef5d9
[root@docker_node1 ~]# docker ps 
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS               NAMES
5bd8e32089c0        linux1874/myimg:v0.1   "/bin/sh -c '/bin/ht…"   8 seconds ago       Up 7 seconds                            myweb1
[root@docker_node1 ~]#

  提示:因为我建立的是私有仓库,所以只有登录仓库后才可以下载;如果是公有仓库就不需要登录;从上面的信息看,我们下载的镜像已经下载到本地,并启动为容器了;

  9、在宿主机上访问容器内部httpd服务,看看是否能够响应我们提供的主页?

[root@docker_node1 ~]# docker container inspect -f "{{.NetworkSettings.Networks.bridge.IPAddress}}" myweb1
172.17.0.2
[root@docker_node1 ~]# curl http://172.17.0.2
this test file
[root@docker_node1 ~]#

  提示:可以看到是可以访问到内部容器的httpd服务,响应给我们的主页也是我们自己制作镜像时提供的主页文件;

  到此基于现有容器制作镜像、分发镜像到仓库的过程就测试完了;

相关文章
Docker容器技术-优化Docker镜像
日志一.优化Docker镜像 1.降低部署时间 一个大的Docker应用是如何影响在新Docker宿主机上的部署时间. (1)编写Dockerfile创建一个大Docker镜像 [root@bogon ~ ...
容器技术|Docker三剑客之docker-compose
日志三剑客简介 docker-machine docker技术是基于Linux内核的cgroup技术实现的,那么问题来了,在非Linux平台上是否就不能使用docker技术了呢?答案是可以的,不过显然需要 ...
2
容器技术|Docker三剑客之docker-machine
日志docker-machine是什么? ocker-machine就是docker公司官方提出的,用于在各种平台上快速创建具有docker服务的虚拟机的技术,甚至可以通过指定driver来定制虚拟机的实 ...
1
Docker容器技术-镜像分发
日志一.镜像分发 1.镜像及镜像库的命名方式 指定镜像名称和标签的方法: 在狗偶见镜像时 通过docker tag命令 [root@bogon ~]# cd identidock/ [root@bogon ...
1
在Heroku容器注册表上使用Jenkins部署Docker镜像
问答我正在尝试在Heroku上部署jenkinsci/docker,并且在编写我的Dockerfile时遇到问题. 当我通过heroku容器在Heroku容器注册表上推送Docker镜像时:推送web,我 ...
2
gitlab runner使用错误的docker镜像构建容器
问答我在我的VM上设置了一个gitlab-ci-multi-runner. 在构建过程中,我提供了一个包含所有依赖项的docker容器. 但是当我运行它时,跑步者使用不同的(错误的)泊坞窗图像作为他的构建 ...
1
将Docker镜像作为容器运行
问答我从dockerfile构建一个docker镜像.我看到图像建成功,但我该怎么办呢?应该不能够作为容器运行? 新的docker所以可能在我的结束的误解,任何帮助将是伟大的.::运行它的具体方式取决于是 ...
amazon-web-services – 如何从亚马逊上正在运行的容器创建新的docker镜像?
问答这是我的问题: 我有一个在亚马逊ECS上运行docker镜像的任务,但我想从容器的运行实例中创建一个新的docker镜像. 我在Amazon Ecs上看到了实例的ID,我已经制作了一个AMI,但我想制 ...
1
如何创建与主机用户具有相同文件权限的docker镜像/容器
问答在组"usergroup1"中以名称"username1"的用户启动docker容器时. 并且该容器在本地文件系统上具有卷的文件/文件夹: 例如. $usern ...
1
我该如何使用Postgresql docker镜像/容器?
问答我是码头工人的新手.我仍然试图绕过这一切. 我正在构建一个节点应用程序(REST api),使用Postgresql来存储我的数据. 我花了几天时间学习码头工具,但我不确定我是否按照我应该的方式做事. ...
amazon-web-services – Docker镜像从VSTS构建/发布定义推入AWS弹性容器注册表(ECR)
问答我们有一个python docker镜像需要在AWS容器注册表中构建/发布(CI / CD). 目前AWS不支持使用docker hub私有存储库运行docker任务,因此我们必须使用ECR而不是do ...
1
Docker镜像vs容器
问答Docker镜像和容器如何不同? 当使用docker时,我们从一个基础镜像开始.我们启动它,创建更改,这些更改保存在层中形成另一个图像. 所以最终我有一个图像为我的Postgres和一个图像为我的网络 ...
1
安全性 – 使用在Docker容器内运行的Jenkins构建Docker镜像
问答我正在阅读this article关于设置Jenkins在Docker容器内运行的方式,Jenkins能够以自己的方式构建Docker镜像.虽然这种解决方案有效,但作者也指出了一些安全问题. 主要的安 ...
如何在Sonarqube docker镜像中跨容器调用保持配置和分析
问答Sonarqube官方docker镜像,不会持久保存任何配置更改,如:创建用户,更改root密码甚至安装新插件. 重新启动容器后,所有配置更改都将消失,安装的插件将丢失.重启后,即使项目的密钥及其先前 ...
docker容器不会以Mysql docker镜像开始
问答我使用带有mysql官方图像的docker容器来创建超过11个数据库容器(container1到container11).设置完成后,所有容器都运行正常,直到container9.在container ...
2
Docker容器技术的核心
日志容器技术的核心 所谓容器,其实是由Linux Namespace.Linux Cgroups和rootfs三种技术构建出来的进程的隔离环境 对于Docker项目来说,其实最核心就是为待创建的用户进程: ...
Linux下正确修改Docker镜像和容器的默认存储位置,亲测有效
日志我们通过 yum 的方式安装完Docker环境后,它默认的存储位置是 /var/lib/docker,默认的 pid 存放位置是 /var/run/docker.pid. 如果仅仅是做测试,我们可能没 ...
1
Docker 镜像、容器、仓库的概念及基本操作
日志Docker 包括三个基本概念: 镜像(Image)容器(Container)仓库(Repository) 这三部分组成了Docker的整个生命周期,如下图所示,容器是由镜像实例化而来的,这和我们学习 ...
1
Docker 镜像,dump openjdk-alpine 镜像容器中的 jvm
日志默认情况下,我们使用的都是 jre 版本的 openjdk,当容器启动卡住不动的时候,看不出来任何问题. 此时如果能 dump 就能知道线程在干啥,也能找到一些大概的问题. 此时 jre 版本的镜像就 ...
1
docker镜像创建redis5.0.3容器集群
日志拉取redis5.0.3镜像  # docker pull daocloud.io/library/redis:5.0.3 [root@localhost ~]# docker pull daoclo ...
1