讲一个简单的案例

@哈希码用来校验,这样子会安全

MAINTANIER可能将会被LABEL代替,仅仅说说明一下镜像信息罢了。

1、首先是我们创建一个镜像

[root@ELK-chaofeng08 ~]# mkdir /docker
[root@ELK-chaofeng08 ~]# cd /docker
[root@ELK-chaofeng08 docker]# vim Dockerfile

输入以下内容:

#Description: httpd image
FROM busybox:latest
MAINTAINER "ChaoFeng <chaofeng@qq.com>"
COPY index.html /data/web/html

正文的第一行必须是FROM开头。#号表示注释。

CPOY命令是复制一个文件,index.html这个文件必须与Dockerfile这个文件同级存放或者在子目录下也可以。

不过我在这里踩坑了,因为我的COPY那一行写错了。

正确的是:

2、接下来我们创建index.html

[root@ELK-chaofeng08 docker]# echo "How are you" > index.html
[root@ELK-chaofeng08 docker]# cat index.html
How are you
[root@ELK-chaofeng08 docker]# ls
Dockerfile index.html

3、然后创建目标目录

[root@ELK-chaofeng08 docker]# mkdir -pv /data/web/html
mkdir: created directory ‘/data/web’
mkdir: created directory ‘/data/web/html’

4、开始制作镜像。

制作的时候最好加上标签

5、查看一下我们制作的新镜像

6、启动一下看看。

这个指令的用法是最常见的。

[root@ELK-chaofeng08 docker]# docker run --name tinyweb1 --rm tinyhttpd:v0.1.1 cat /data/web/html/index.html
How are you
[root@ELK-chaofeng08 docker]#

后面的cat指令是EXEC的指令,也就是说我们一启动容器后不运行默认的命令,而是运行我们指定的cat命令,运行完毕后退出容器,我还设置了--rm参数,表示容器停止后就删除它。要学会这个用法

看的出来我们成功了。

二、如何复制一个目录呢?

比如现在我们想把物理机下的/etc/yum.repos.d目录下的所有文件复制到容器内的/etc/yum.repos.d/的目录下

1、先把物理机下的/etc/yum.repos.d这个目录复制到Dockerfile同级的目录下(子目录下也行)

[root@ELK-chaofeng08 docker]# cp -r /etc/yum.repos.d ./
[root@ELK-chaofeng08 docker]# ls
Dockerfile index.html yum.repos.d

2、编辑Dockerfile文件

COPY可以用多个。COPY命令的用法原则是能用一条来代替就不要用多条,因为每一个COPY命令就会生成一个镜像层。层越多,联合挂载效率越低。

3、开始制作

4、查看一下新的镜像

5、查看一下新的镜像下是否有新的文件

说明成功了。

三、ADD命令的用法,

1、编辑Dockerfile文件

2、制作新的镜像

3、查看新的镜像

4、查看新的镜像下的nginx的tar包

成功了。

四、ADD命令的解压功能。

ADD命令不仅可以从互联网下载文件(压缩文件,普通文件等)并放入新的镜像内,还可以根据压缩文件的类型选择算法实现解压操作,如下所示:

1、首先是压缩文件必须是放在本地才可以。

我们以phpmyadmin文件为例

2、编辑Dockerfile文件

3、开始制作镜像

4、查看新的镜像下的phpmyadmin的展开文件

成功。

注意:ADD命令可以从指定的URL向互联网下载各种类型的文件到新镜像,也可以将一个压缩文件解压放入新的镜像,但是不能同时既进行下载tar压缩文件又进行压缩tar文件到新镜像里面。

五、指定WORKDIR目录路径

六、指定存储卷

不过只能指定docker自己管理的卷,不能指定我们绑定的外部卷的存储路径

比如:

七、暴露端口给外部的宿主机

相当于自动帮我们生成一个DNAT端口。跟以前的-p参数一样的功能。

不过用法也比较限制,只能动态绑定宿主机的动态端口到容器的固定端口。不能绑定指定宿主的ip和指定的端口。但是这有时候也是一种安全的机制。

案例:

因为第一次我们编辑了一个index.html文件,在/data/web/html目录下存放这,我们直接使用这个文件,。

1、编辑dockerfile文件

2、重新制作新的镜像

3、查看这个新镜像

4、启动这个新镜像

5、我们去查看这个容器的ip

6、访问一下这个容器的80端口

非常好。成功

像这种在配置文件中暴露的端口在外部是看不到的,这是半暴露状态,如果想要全部暴露,加上-P参数。比如:

所以我们可以加上-P参数指定为暴露端口给外部

7、加上-P参数

8、再来查看一下

我们就可以在外部访问了

八、ENV和RUN命令解释,

RUN命令是Dockerfile文件中的一个可以执行命令的参数,比如:

1、编辑dockerfile文件

2、制作新镜像

3、启动新镜像查看

成功了。

在Dockerfile中定义的环境变量是可以用在容器启动以后引用的变量

注意:RUN命令是可以运行多次的。后面的命令可以使用“\”表示续行。所有的RUN操作是基于基础镜像的,因此要注意环境。

九、CMD和ENTRYPOINT

  注意:json数组要使用双引号。

ENTRYPOINT

两种格式:

ENTRYPOINT ["executable", "param1", "param2"]

ENTRYPOINT command param1 param2 (shell中执行)
配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。每个 Dockerfile 中只能有一个 ENTRYPOINT ,当指定多个时,只有最后一个起效。 CMD 支持三种格式 CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;
CMD command param1 param2 在 /bin/bash 中执行,提供给需要交互的应用;
CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数;
指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。

ENTRYPOINT 和 CMD 的区别:ENTRYPOINT 指定了该镜像启动时的入口,CMD则指定了容器启动时的命令,当两者共用时,完整的启动命令像是 ENTRYPOINT + CMD 这样。使用 ENTRYPOINT 的好处是在我们启动镜像就像是启动了一个可执行程序,在 CMD 上仅需要指定参数;另外在我们需要自定义 CMD 时不容易出错。

使用 CMD 的 Dockerfile:

[root@sta2 test]# cat Dockerfile
FROM mysql
CMD ["echo","test"]

使用 ENTRYPOINT 的 Dockerfile:

[root@sta2 entrypoint]#  cat  Dockerfile
FROM mysql
ENTRYPOINT ["echo","test"]

结论:ENTRYPOINT 不能覆盖掉执行时的参数,CMD 可以掉覆盖默认的参数。

可以使用以下命令覆盖默认的参数,方便调试 Dockerfile 中的 bug:
[root@sta2 entrypoint]# docker run -it --entrypoint=/bin/bash feiyu/entrypoint:1

案例演示:

制作一个nginx(重点掌握)

1、先制作Dockerfile文件

FROM nginx:1.14-alpine
LABEL maintainer="Chaofeng <chaofeng@chaofeng.com>"

ENV NGX_DOC_ROOT='/data/web/html/'

ADD entrypoint.sh /bin/

CMD ["/usr/sbin/nginx","-g","daemon off;"]

ENTRYPOINT ["/bin/entrypoint.sh"]

2、制作entrypoint.sh文件

#!/bin/sh

cat > /etc/nginx/conf.d/www.conf << EOF
server{
server_name ${HOSTNAME};
listen ${IP:-0.0.0.0}:${PORT:-};
root ${NGX_DOC_ROOT:-/usr/share/nginx/html};
}
EOF exec "$@"

3、给entrypoint.sh文件授权

chmod +x entrypoint.sh

4、制作docker镜像

[root@ELK-chaofeng08 docker3]# docker build -t tinyweb:v0.3.2 ./
Sending build context to Docker daemon .072kB
Step / : FROM nginx:1.14-alpine
---> 66952fd0a8ef
Step / : LABEL maintainer="Chaofeng <chaofeng@chaofeng.com>"
---> Using cache
---> 9b06b920ce9b
Step / : ENV NGX_DOC_ROOT='/data/web/html/'
---> Using cache
---> 9346cf0174b9
Step / : ADD entrypoint.sh /bin/
---> c8f80cdc1321
Step / : CMD ["/usr/sbin/nginx","-g","daemon off;"]
---> Running in 20bace9c162d
Removing intermediate container 20bace9c162d
---> 4cbfa737e80f
Step / : ENTRYPOINT ["/bin/entrypoint.sh"]
---> Running in babe021b35b9
Removing intermediate container babe021b35b9
---> b474e7c54539
Successfully built b474e7c54539
Successfully tagged tinyweb:v0.3.2

5、启动镜像

[root@ELK-chaofeng08 docker3]# docker run --name tinyweb1 --rm -P tinyweb:v0.3.2

6、在另一终端查看进程

[root@ELK-chaofeng08 docker3]# docker exec -it tinyweb1 /bin/sh
/ # ps
PID USER TIME COMMAND
root : nginx: master process /usr/sbin/nginx -g daemon off;
nginx : nginx: worker process
root : /bin/sh
root : ps

我们在Dockerfile文件中使用脚本的方式进行传值,我们执行ENTRYPOINT的时候使用的是数组的形式,意思就是把CMD的元素当作是一个个的参数传给ENTRYPOINT,首先是在创建完entrypoint.sh脚本的时候,执行最后一句exec操作,这是把当前nginx的进程作为主进程来执行,因此在这里的ps命令中看到nginx的主进程的PID号是1。

我们设计成脚本的方式是比较好传值的,省去了修改某个参数时重新制作镜像的麻烦,为什么这么说呢?比如下面这个例子:

[root@ELK-chaofeng08 docker3]# docker exec -it tinyweb1 /bin/sh
/ # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0.0.0.0: 0.0.0.0:* LISTEN

此时正好是运行在80端口。

假如此时我想运行在8080端口怎么办呢?可以这样子来

[root@ELK-chaofeng08 docker3]# docker run --name tinyweb1 --rm -P -e 'PORT=8080' tinyweb:v0.3.2

使用-e参数,表示启动容器的时候使用作为环境变量传入

再打开一个终端执行如下:

[root@ELK-chaofeng08 docker3]# docker exec -it tinyweb1 /bin/sh
/ # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0.0.0.0: 0.0.0.0:* LISTEN
tcp 0.0.0.0: 0.0.0.0:* LISTEN

不仅运行在了默认的80端口,还运行在了8080端口,非常的方便。这就是脚本传值的作用。这里还要理解entrypoint.sh有个“${PORT:-80}”是什么意思呢?就是如果环境中有默认的PORT的值,那么此时PORT就有值然后就使用默认的值,如果没有值,则使用80端口。那么至于为什么上面还会有80端口呢?这是因为nginx还有自己主配置文件的默认端口是80端口(不要搞混淆了)。

十、HEALTHCHECK检测

案例演示

在dockerfile中加入如下内容:

然后制作一个新的镜像并启动

每隔默认的30s检测一次是否成功。

十一、在docker build阶段传递参数ARG

案例:

修改dockerfile

然后构建镜像时传值

需要注意的是,我们之前学习的命令中传递环境变量参数的时候,使用的都是docker run操作,但是如果我们想在docker build阶段传入参数的值,则要是有docker build –build-tag参数了。

十二、ONBUILD

Dockfile制作镜像的更多相关文章

  1. docker-使用Dockerfile制作镜像

    最近项目中有使用docker,组内做了关于docker的培训,然后自己跟着研究了一下,大概了解如何使用.我是基于tomcat镜像制作(不需要安装jdk,配置环境变量),基于centos镜像制作需要安装 ...

  2. 【制作镜像】BCEC制作镜像

    如要制作的新镜像已存在标准版本镜像,即linux发行版本相同(此处指CentOS6.5 64位),可利用BCEC制作. 在BCEC创建centos6.5系统的可联外网的虚机,ssh到此虚机,用yum方 ...

  3. Docker系列06—基于容器制作镜像并上传到Docker Registry

    本文收录在容器技术学习系列文章总目录 1.制作镜像 1.1 镜像的生成途径 基于容器制作 dockerfile,docker build 本篇主要详细讲解基于容器制作镜像:基于dockerfile 制 ...

  4. Docker学习笔记之二:制作镜像并PUSH

    Pull 如果是Public的(docker官方仓库和加速器) 直接 docker pull ubuntu:16.04 即可 若是私有的 首先登陆 docker login 仓库Host 之后 doc ...

  5. OpenStack单节点制作镜像

    1.创建快照 已修改后的时刻为记录,进行制作镜像,选择要制作镜像的虚拟机,点击创建快照,在所弹出的对话框中输入所创建的镜像名称 生成了一个镜像,类型为Snapshot 2.保存镜像 查看镜像列表 [r ...

  6. WIN7安装Docker Toolbox、制作镜像并发到阿里云

    一.安装Docker Toolbox,并配置国内源加速 WIndows7不支持Hyper-v,所以只能采用Docker Toolbox的方式使用Docker.传送门:http://mirrors.al ...

  7. Docker 0x05: Dockerfile制作镜像

    目录 Dockerfile制作镜像 一句话什么是dockerfile dockerfile脚本指令 小结 Dockerfile制作镜像 dockerfile 可以是制作自己镜像的脚本文件,按照这个脚本 ...

  8. 制作镜像文件工具packer

    openstack镜像制作要在openstack上创建虚拟机,必然要使用到虚拟机镜像. 对于普通用户,可以使用已经创建好的虚拟机镜像.一般是操作系统官方构建并提供的. 某些用户可以有自己独特的需求,需 ...

  9. 记录 Docker 的学习过程 (dockerfile自动制作镜像)

    自动制作镜像 通过编写dockerfile来自动创建镜像 #vi Dockerfile #编辑dockerfile文件,一定要以这个名字命名 #cat Dockerfile #导入哪个基础镜像FROM ...

随机推荐

  1. Java线程实现与安全

    目录 1. 线程的实现 线程的三种实现方式 Java线程的实现与调度 2. 线程安全 Java的五种共享数据 保证线程安全的三种方式 前言 本篇博文主要是是在Java内存模型的基础上介绍Java线程更 ...

  2. QTimer 的使用

    QTimer(重复和单发计时器) 应用 QTimer 时,先创建一个 QTimer 类,利用 connect 将 timeout() 与对应槽函数连接,在调用 start() 函数设置定时器时间间隔, ...

  3. 前端学习(一) —— HTML

    1.js跳转 window.location.href='url'; 2.div显示与隐藏 hide() show() 3.判断是否为一个字符串是否为整形 function isInt(str){ v ...

  4. [转]node-sass 安装失败的各种坑

    本文转自:https://blog.csdn.net/weixin_42406046/article/details/80604623?tdsourcetag=s_pctim_aiomsg 版权声明: ...

  5. 无法将文件“..\bin\Debug \**.dll”复制到“bin\**.dll”。对路径“bin \**.dll”的访问被拒绝。

    1.方法一: 将bin的只读属性去掉,就OK. 2.方法二: 直接关掉项目,重新打开.

  6. Java学习笔记之——static关键字

    static属于类的,不属于任何一个对象的 static关键字的应用场景: 1.静态代码块:在类下用static修饰的代码块 static{ 代码: } 只能执行一次,是在第一次使用类之前执行 类加载 ...

  7. ANOVA (paper from the onlinestat)

    Introduction Author(s) David M. Lane Prerequisites Variance, Significance Testing,All Pairwise Compa ...

  8. MySQL主从 常见的错误及解决方案

    一.错误日志解析: (1) [ERROR]1452:无法在外键的表插入参考主键没有的数据 1452:无法在外键的表插入或更新参考主键没有的数据.由于item_discovery.itemid字段(外键 ...

  9. 全面掌握Node命令选项

    全面掌握Node命令选项 译者按:作为Node.js开发者,有必要全面了解一下节点命令的所有选项,这样在关键时刻才能得心应手. 原文:掌握Node.js的CLI和命令行选项 译者:Fundebug 为 ...

  10. mysql date_format()函数

    DATE_FORMAT(DATE,FORMAT)函数 占位符 说明 %a 缩写的星期几(Sun.....Sat) %b 缩写的月份(Jan.....Dec)  %c 数字形式的月份(1.......1 ...