构建docker镜像

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 构建docker镜像

1.创建Docker Hub账号

网址:https://hub.docker.com/ 注册.

  • 登录
$ sudo docker login

2.用docker commit命令创建镜像

  • 创建一个要进行修改的定制容器
$ sudo docker run -i -t ubuntu /bin/bash                   
root@7dfcf4332617:/# 
  • 在容器中安装apache软件包
root@7dfcf4332617:/# apt-get -yqq update
root@7dfcf4332617:/# apt-get -y install apache2
  • 提交定制容器
$ sudo docker commit 7dfcf4332617 hiekay/apache2
  • 检查新创建的镜像
$ sudo docker images hiekay/apache2   
          
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
hiekay/apache2      latest              d36fa6c04e5b        About a minute ago   205MB
  • 提交另一个新的定制容器
$ sudo docker commit -m="A new custom image" --author="hiekay" 7dfcf4332617 hiekay/apache2:webserver

解析:
-m 指定提交信息,--author指定作者信息, ID:7dfcf4332617 ,hiekay/apache2 用户名和仓库名, 标签:webserver

  • 查看镜像的详细信息
$ sudo docker inspect  hiekay/apache2:webserver                                                      

 
[
    {
        "Id": "sha256:dfda6a2c29aac1aa25b188f5b5f1a8b0d6cf63c92df0bacb4f062be312ebe9c2",
        "RepoTags": [
            "hiekay/apache2:webserver"
        ],
........
  • 运行新容器
$ sudo docker run -i -t hiekay/apache2:webserver /bin/bash
root@b7a12bac939e:/# 

3.用Dockerfile创建镜像

用Dockerfile的自定义文件和docker build 命令来构建镜像.Dockerfile使用基本的基于DSL语法的指令来构建一个Docker镜像,之后使用docker build命令基于该Dockerfile中的指令构建一个新的镜像.

创建第一个Dockerfile
  • 创建一个示例仓库
$ mkdir static_web
$ cd static_web
$ touch Dockerfile

目录static_web 用来保存Dockefile ,这个目录也是我们的构建环境, Docker称此环境为上下文或者构建上下文. Docker 会在构建镜像时将构建上下文和该上下文中的文件和目录上传到Docker守护进程.

  • 第一个Dockerfile
    例子: 创建一个空Dockerfile,通过Dockerfile 构建一个能作为Web服务器的Docker镜像.
#Version: 0.0.1
FROM ubuntu:18.04
MAINTAINER hiekay "hikay5230@gmail.com"
RUN apt-get update
RUN apt-get install -y nginx
RUN echo 'Hi,I am in your container' > /usr/share/nginx/html/index.html
EXPOSE 80

该Dockerfile由一系列指令和参数组成.
每条指令,如FROM都必须大写,后面跟一个参数.
指令会按顺序从上到下执行.
每条指令都会去创建一个新的镜像层并对镜像进行提交.

流程:
  • Docker从基础镜像运行一个容器.
  • 执行一条指令,对容器做出修改.
  • 执行类似docker commit 的操作,提交一个新的镜像层.
  • Docker再基于刚提交的镜像运行一个新容器.
  • 执行Dockerfile中的下一个指令,直到所有指令都执行完毕.
    所以,如果Dockerfile某些原因(某指令失败了)没有正常结束.也将得到一个可以使用的镜像.
解析
  • 每个Docker的第一条指令都应该是FROM,FROM指令指定了一个已经存在的镜像,后续指令都将基于该镜像进行,这个镜像被称为基础镜像.
  • MAINTAINER指令设置作者和邮箱
  • RUN指令,会在当前镜像中运行指定的命令,默认RUN指令会在shell中使用命令包装器/bin/sh -c 运行. 如果是在一个不支持shell的平台或者不希望在shell中运行,可以用exec 格式的RUN指令
    如:
RUN [ "apt-get", " install ", "-y", "nginx" ]

在这种方式中,使用一个数组来指定要运行的命令和传递给该命令的每个参数.

  • EXPOSE指令,是设置容器的指定端口. 也可以指定多个端口.

4.基于Dockerfile构建新镜像

执行docker build 命令时,Dockerfile中的所有命令都会执行并提交,成功结束后返回一个新镜像.

  • 运行Dockerfile
$ cd static_web
$ sudo docker build -t="hiekay/static_web" . 
//开始运行
sending build context to Docker daemon  2.048kB
Step 1/6 : FROM ubuntu:18.04
18.04: Pulling from library/ubuntu
Digest: sha256:29934af957c53004d7fb6340139880d23fb1952505a15d69a03af0d1418878cb
Status: Downloaded newer image for ubuntu:18.04
 ---> ea4c82dcd15a
Step 2/6 : MAINTAINER hiekay "hikay5230@gmail.com"
 ---> Running in 82ebf098abd8
Removing intermediate container 82ebf098abd8
 ---> b8405a62db26
Step 3/6 : RUN apt-get update

其中 -t 选项设置了仓库和名称.
还可以设置标签:

sudo docker build -t="hiekay/static_web:v1" . 

如果不设置标签,默认标签是latest标签.
命令最后的 . 告诉Docker到本地目录去找Dockerfile , 也可以指定一个git 仓库的源地址来指定Dockerfile的地址
如:

sudo docker build -t="hiekay/static_web:v1" git@github.com:hiekay/docker-static-_web

在该git仓库根目录下存折Dockerfile文件.
其中:
sending build context to Docker daemon 2.048kB
是将构建上下文上传到Docker守护进程.

  • 注意:
    如果在构建上下文的根目录下存在.dockerignore命名的文件, 这个该文件用来设置哪些文件不会被上传到构建上下文中.

5.指令失败时会怎样

假如在第四部写错了:ngin

$ cd static_web
$ sudo docker build -t="hiekay/static_web" . 
//开始运行
Sending build context to Docker daemon  2.048kB
Step 1/6 : FROM ubuntu:18.04
 ---> ea4c82dcd15a
Step 2/6 : MAINTAINER hiekay "hikay5230@gmail.com"
 ---> Using cache
 ---> b8405a62db26
Step 3/6 : RUN apt-get update
 ---> Using cache
 ---> a7b7791c3818
Step 4/6 : RUN apt-get install -y ngin
 ---> Running in fabeeceeefe2
Reading package lists...
Building dependency tree...
Reading state information...
E: Unable to locate package ngin
The command '/bin/sh -c apt-get install -y ngin' returned a non-zero code: 100

报错,E: Unable to locate package ngin
最后成功的一层ID是:a7b7791c3818

  • 基于最后成功步骤创建新容器
    再运行: apt-get install -y ngin 并指定正确的包名,进一步调试,解决问题.就可以退出容器了,使用正确的报名修改Dockerfile,之后再进行构建.
$ sudo docker run -i -t a7b7791c3818 /bin/bash
root@9988a4ab2845:/# 
root@9988a4ab2845:/# apt-get install -y ngin

6.Dockerfile 和构建缓存

因为每一步的构建过程都会将结果提交为镜像,所以它会将之前的镜像层看做缓存.

  • 忽略Dockerfile的构建缓存
$ sudo docker build --no-cache -t="hiekay/static_web" .

7.基于构建缓存的Dockerfile模板

构建缓存的好处是可以实现简单的Dockerfile模板.在自己的Dockerfile文件顶部使用相同的指令模板,比如Ubuntu.

  • Ubuntu系统的Dockerfile模板
#Version: 0.0.1
FROM ubuntu:18.04
MAINTAINER hiekay "hikay5230@gmail.com"
ENV REFRESHED_AT 2018-11-1
RUN apt-get -qq update
  • 解析:
    首先通过FROM指令为镜像设置基础镜像Ubuntu:18.04 , 然后使用MAINTAINER 添加自己的信息. 之后使用 ENV 设置 环境变量.设置REFRESHED_AT的环境变量用来表示该镜像模板最后的更新时间 .最后使用RUN指令运行apt-get -qq update 命令. 该指令运行时将会刷新APT包的缓存,用来确保我们能将要安装的每个软件包都更新到最新版本.

有了这个模板,如果想刷新一个构建,只需要修改ENV指令中的日期.这使Docker在命令ENV指令时开始重置这个缓存,并运行后续指令无须依赖该缓存. 也就是说, RUN apt-get update 这条指令将会被再次执行,包缓存也将会被刷新为最新内容.
可以扩展此模板,比如适配到不同的平台或者添加额外的需求.

  • 比如支持Fedora Dockerfile模板
FROM fedora:20
MAINTAINER hiekay "hikay5230@gmail.com"
ENV REFRESHED_AT 2018-11-1
RUN yum -y -q upgrade 

在Fedora中使用Yum实现了与上面的Ubuntu例子中非常类似的功能.

8.查看新镜像

  • 列出新的Docker镜像
$ sudo docker images hiekay/static_web
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hiekay/static_web   latest              7e35e0a7fc62        3 hours ago         169MB

深入探究镜像是如何构建出来的,使用docker history命令

  • 使用docker history 命令
$ sudo docker history 7e35e0a7fc62  

IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
7e35e0a7fc62        3 hours ago         /bin/sh -c #(nop)  EXPOSE 80                    0B                  
2f6d2e9be7ac        3 hours ago         /bin/sh -c echo 'Hi,I am in your container' …   26B                 
4c7337c294ac        3 hours ago         /bin/sh -c apt-get install -y nginx             59.7MB              
489c8164d6af        3 hours ago         /bin/sh -c apt-get update                       23.8MB              
c8288775012d        3 hours ago         /bin/sh -c #(nop)  MAINTAINER hiekay "hikay5…   0B                  
ea4c82dcd15a        13 days ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           13 days ago         /bin/sh -c mkdir -p /run/systemd && echo 'do…   7B                  
<missing>           13 days ago         /bin/sh -c rm -rf /var/lib/apt/lists/*          0B                  
<missing>           13 days ago         /bin/sh -c set -xe   && echo '#!/bin/sh' > /…   745B                
<missing>           13 days ago         /bin/sh -c #(nop) ADD file:bcd068f67af2788db…   85.8MB

9.从新镜像启动一个容器

$ sudo docker run -d -p 80 --name static_web hiekay/static_web nginx -g "daemon off;"
09bb5531cbc24930ad35da95dd0acd52dd933c5996ae89e238b509053b7f8c1d
  • 解析:
  1. run命令运行一个名字为static_web的新容器, -d 选项,告诉Docker以分离(detached)的方式在后台运行.适合运行类似Nginx守护进程这样的需要长时间运行的进程. 并指定了需要在容器中运行的命令:nginx -g "daemon off;" 这将以前台运行的方式启动nginx 来作为我们的Web服务器.

其中-p标志,用来控制Docker公开哪些网络端口给外部宿主机.
两种方法分配端口:

  • Docker可以在宿主机上随机选择一个位于49153~65535的一个比较大的端口号来映射到容器中80端口上.
  • 可以在Docker宿主机中指定一个具体的端口号来映射到容器中的80端口上.
  • 查看Docker端口映射情况
$ sudo docker ps -l
  • dockerport 命令查看
$ sudo docker port 09bb5531cbc2 80
                                                  
80/tcp -> 127.0.0.1:32768
  • 通过-p选项映射到特定端口
$ sudo docker run -d -p 80:80 --name static_web hiekay/static_web nginx -g "daemon off;"
  • 绑定不同的端口
$ sudo docker run -d -p 8080:80 --name static_web hiekay/static_web nginx -g "daemon off;"
  • 绑定到特定的网络接口
$ sudo docker run -d -p 127.0.0.1:80:80 --name static_web hiekay/static_web nginx -g "daemon off;"

绑定到了宿主机127.0.0.1这个IP的80端口上.

  • 绑定到特定的网络接口的随机端口
$ sudo docker run -d -p 127.0.0.1::80 --name static_web hiekay/static_web nginx -g "daemon off;"
  • 扩展
    可以使用 /udp后缀指定UDP端口

其中提供参数-P 用来对外公开在Dockerfile中的EXPOSE指令中设置的所有端口

  • 使用docker run命令对外公开端口
$ sudo docker run -d -P --name static_web hiekay/static_web nginx -g "daemon off;"

该命令会将容器内的80端口对本地宿主机公开,绑定宿主机的随机端口. 会将用来构建该镜像的Dockerfile文件中EXPOSE指令指定的其他端口也公开.

有了这个端口号,我们可以用本地宿主机IP或者127.0.0.1的localhost 链接到运行中的容器了.

  • 使用curl连接到容器
$ curl localhost:32768

//成功返回:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

10.将镜像推送到Docker Hub

  • docker push
    推送Docker镜像
$ sudo docker push hiekay/static_web

The push refers to repository [docker.io/hiekay/static_web]
......

成功后,可以在Docker Hub上看到我们上传的镜像.
image.png

11.删除镜像

sudo docker rmi hiekay/static_web

如果要删除一个Docker Hub上的镜像仓库,需要登录Docker Hub后使用Delete repository链接来删除.
image.png

  • 删除所有镜像
sudo docker rmi 'docker images -a -q'

12.运行自己的Docker Registry

  • 运行基于容器的Registry
sudo docker run -p 5000:5000 registry
  • 查看hiekay/static_web
sudo docker images hiekay/static_web
  • 使用新的Registry 为镜像打标签
sudo docker tag 某个ID docker.example.com:5000/hiekay/static_web
  • 将镜像推送到新Registry
sudo docker push docker.example.com:5000/hiekay/static_web
  • 从本地Registry构建新的容器
sudo docker run -t -i docker.example.com:5000/hiekay/static_web /bin/bash
目录
相关文章
|
18天前
|
运维 Kubernetes Docker
利用Docker和Kubernetes构建微服务架构
利用Docker和Kubernetes构建微服务架构
|
22天前
|
缓存 Linux 网络安全
docker的镜像无法下载如何解决?
【10月更文挑战第31天】docker的镜像无法下载如何解决?
820 29
|
18天前
|
存储 关系型数据库 Linux
【赵渝强老师】什么是Docker的镜像
Docker镜像是一个只读模板,包含应用程序及其运行所需的依赖环境。镜像采用分层文件系统,每次修改都会以读写层形式添加到原只读模板上。内核bootfs用于加载Linux内核,根镜像相当于操作系统,上方为应用层。镜像在物理存储上是一系列文件的集合,默认存储路径为“/var/lib/docker”。
|
24天前
|
存储 监控 Linux
docker构建镜像详解!!!
本文回顾了Docker的基本命令和管理技巧,包括容器和镜像的增删改查操作,容器的生命周期管理,以及如何通过端口映射和数据卷实现容器与宿主机之间的网络通信和数据持久化。文章还详细介绍了如何使用Docker部署一个简单的Web应用,并通过数据卷映射实现配置文件和日志的管理。最后,文章总结了如何制作自定义镜像,包括Nginx、Python3和CentOS镜像,以及如何制作私有云盘镜像。
108 2
|
25天前
|
关系型数据库 MySQL Docker
docker环境下mysql镜像启动后权限更改问题的解决
在Docker环境下运行MySQL容器时,权限问题是一个常见的困扰。通过正确设置目录和文件的权限,可以确保MySQL容器顺利启动并正常运行。本文提供了多种解决方案,包括在主机上设置正确的权限、使用Dockerfile和Docker Compose进行配置、在容器启动后手动更改权限以及使用 `init`脚本自动更改权限。根据实际情况选择合适的方法,可以有效解决MySQL容器启动后的权限问题。希望本文对您在Docker环境下运行MySQL容器有所帮助。
54 1
|
27天前
|
存储 Java 开发者
成功优化!Java 基础 Docker 镜像从 674MB 缩减到 58MB 的经验分享
本文分享了如何通过 jlink 和 jdeps 工具将 Java 基础 Docker 镜像从 674MB 优化至 58MB 的经验。首先介绍了选择合适的基础镜像的重要性,然后详细讲解了使用 jlink 构建自定义 JRE 镜像的方法,并通过 jdeps 自动化模块依赖分析,最终实现了镜像的大幅缩减。此外,文章还提供了实用的 .dockerignore 文件技巧和选择安全、兼容的基础镜像的建议,帮助开发者提升镜像优化的效果。
|
18天前
|
API Docker 容器
【赵渝强老师】构建Docker Swarm集群
本文介绍了如何使用三台虚拟主机构建Docker Swarm集群。首先在master节点上初始化集群,然后通过特定命令将node1和node2作为worker节点加入集群。最后,在master节点上查看集群的节点信息,确认集群构建成功。文中还提供了相关图片和视频教程,帮助读者更好地理解和操作。
|
18天前
|
缓存 JavaScript 安全
深入理解Docker镜像构建过程
深入理解Docker镜像构建过程
55 0
|
4月前
|
存储 安全 Ubuntu
Docker 镜像与 Docker 容器的区别
【8月更文挑战第27天】
338 5
|
4月前
|
存储 Ubuntu 应用服务中间件
在Docker中,怎么快速查看本地的镜像和容器?
在Docker中,怎么快速查看本地的镜像和容器?