使用Dockerfile来构建镜像
Dockerfile原理
关于Docker中使用Dockerfile来构建镜像,可以简单的理解为:将所有的操作都写在一个脚本中,这个脚本的名称就叫Dockerfile,执行构建镜像的命令时,就会去执行这个命令。
上面只是通俗的说法,其实,你写完Dockerfile之后,执行构建镜像的时候,并不是直接执行Dockerfile中命令,而是将这个文件所在目录的所有文件,都交给docker的守护进程,让docker守护进程来解析之后,再执行。
上面说的是将Dockerfile所在目录的所有文件,都交给守护进程,至于为什么要这样做,待会再解释。
但是,如果是初学Dockerfile,建议建立一个空的目录,在空目录中创建一个Dockerfile文件。
创建Dockerfile
-> ~ # mkdir TestDockerfile
-> ~ # cd TestDockerfile
-> TestDockerfile # touch Dockerfile
-> TestDockerfile # echo "hello world" > index.html #创建一个测试文件
Dockerfile实例
下面的Dockerfile会构建出一个安装有nginx和vim的docker镜像
#VERSION 0.0.1 FROM ubuntu:16.04 MAINTAINER ganlixin ubuntu "1355036599@qq.com" RUN apt-get update && apt-get install -y nginx RUN apt-get install -y vim RUN rm -rf /var/www/html/index.html ADD ./index.html /var/www/html/index.html WORKDIR /var/www/html RUN echo "hello docker" > demo.html WORKDIR /root RUN echo "hello root" > hey.txt ENV SELF_DEFINE_ENVIROMENT_VAR "123456789" RUN echo $SELF_DEFINE_ENVIROMENT_VAR > env_var.html USER root:root COPY index.html /tmp/test CMD /bin/bash EXPOSE 80
下面会针对这个Dockerfile中每一项,进行详细的说明。
Dockerfile指令
注释
在Dockerfile中,每一行“#”之后的内容,都会被当成注释。
一般用来写一些提示信息,比如版本信息,镜像说明
FROM
FROM ubuntu:16.04
表示使用当前Dockerfile在构建镜像时,是基于哪一个镜像。一般来说,不会从零开始构建镜像,一般都会选择一个已有的镜像作为基础,在上面安装各种软件,然后构建出一个加工过的镜像。
示例中,使用ubuntu:16.04作为基础
MAINTAINER
MAINTAINER beyond ubuntu ”1355036599@qq.com"
用来提示用户,这个Dockerfile的作者、以及作者的联系方式
RUN
RUN apt-get update && apt-get install -y nginx
RUN用来执行一条Linux命令,执行的时机:在构建镜像的时候。
不是在使用该镜像创建容器后,运行容器的时候。
一个Dockerfile文件中可以有多个RUN命令,也就是说,在构建镜像时,可以执行多个指定的命令
ADD
ADD ./index.html /var/www/html/index.html
还记得在创建Dockerfile的时候,创建了一个测试文件吗?他的内容是hello world,文件名是index.html
这个命令的作用就是将Dockerfile文件所在目录中的某个文件,添加到要构建的镜像中。
如果将Dockerfile所在的环境叫做外部环境,而构建出的镜像成为内部环境的话,ADD命令的作用就是将外部环境中的文件 添加到 内部环境中。
注意,目标路径,如果不是以 / 结尾,表示的文件;如果以 / 结尾,表示目录
WORKDIR
设置一个工作目录,后面的RUN命令、CMD命令都会在这个工作目录中执行。
相当于cd path
WORKDIR /var/www/html
RUN echo "hello docker" > demo.html
WORKDIR /root
RUN echo "hello root" > hey.txt
上面的代码表示,在/var/www/html目录下的demo.html中输入内容“hello world”;
然后切换工作目录,在/root目录中,在hey.txt中输入内容,“hello root”
ENV
定义环境变量,相当于全局变量
ENV SELF_DEFINE_ENVIROMENT_VAR "123456789"
在镜像中设置一个环境变量,SELF_DEFINE_ENVIROMENT_VAR ,值为123456789
之后可以使用$SELF_DEFINE_ENVIROMENT_VAR来使用这个变量
USER
指定启动容器后,是以什么身份来运行,可以同时设置组和用户
USER root:root
表示启动容器后,是以root组的root身份运行
COPY
COPY命令和ADD命令功能类似,
COPY index.html /tmp/test
将外部环境的index.html拷贝到内部环境/tmp目录下,重命名为test。如果是要将index.html拷贝到/tmp/test目录下,即,将test看作是目录,那么,就要在test后面加 / ,即 /tmp/test/
注意,目标路径,如果不是以 / 结尾,表示的文件;如果以 / 结尾,表示目录
CMD
CMD /bin/bash
表示在使用镜像,启动容器的时候,会运行的命令。
和RUN的区别:
1、RUN是在构建镜像的时候运行,而CMD是在容器启动的时候运行。可以理解为,RUN命令只是在构建时执行一次,而CMD命令在每次启动容器时,都会执行一次。
2、一个Dockerfile中可以有多个RUN命令,多个RUN命令都会执行;而CMD命令虽然可以出现多次,但是只有最后一个会被执行。
3、RUN命令只运行一次,所以说不存在命令覆盖的情况,而CMD会出现命令覆盖的情况(即第2点区别),在启动容器时,如果指定了要执行的命令,那么Dockerfile中的CMD命令同样会被覆盖。
EXPOSE
EXPOSE 80,表示将容器的80端口,映射到外部环境(宿主机)的某个端口上。
可以通过启动容器的时候指定映射到宿主机的哪个端口
构建Docker镜像
使用命令docker build命令即可触发构建操作,但是需要注意,构建时,要指定构建出的镜像名称(使用-t选项)以及tag,以及Dockerfile所在的路径。
一般构建的时候,都是进入到Dockerfile所在的目录
假设现在使用前面的Dockerfile构建一个镜像,镜像名为beyond/test,标签为v1,则执行如下命令
-> ~ # cd TestDockerfile
-> TestDockerfile # docker build -t="beyond/test:v1" .
.......等待
........
.......构建完成
-> TestDockerfile # docker run -i -t --name first_test beyond/test
root@38ff683ba587:~# #进入到容器中
注意,此时,在运行容器的时候,并没有在后面加上/bin/bash,这是因为Dockerfile中CMD命令已经指定了在启动容器时执行的命令。
测试
现在我们逐个检查Dockerfile中的操作是否成功,即,看对应操作的结果是否保留下来
1、看/var/www/html/index.html这个文件的内容是不是hello world
2、看/var/www/html下面是不是有一个demo.html,内容为hello docker
3、看/root目录下hey.txt的内容是不是hello root
4、使用env命令,看是不是有SELF_DEFINE_ENVIROMENT_VAR这个环境变量
5、看/root目录下env_var.html的内容是不是环境变量SELF_DEFINE_ENVIROMENT_VAR的值123456789
6、看一下/tmp/test文件内容是不是hello world
指定宿主机和容器的端口映射
-> TestDockerfile # docker run -d --name second_test -p 8080:80 beyond/test:v1 nginx -g "daemon off;"
7d74273277cc925ae5656591367c5b3cc6e4b9ed90d251123eeaed42b463367c
外部访问你的ip:8080,然后就可以看到结果了。
使用Dockerfile来构建镜像的更多相关文章
- Docker:dockerfile自动构建镜像 [六]
一.手动docker镜像的缺点 相对于手动制作的docker镜像,使用dockerfile构建的镜像有以下优点: 1.dockerfile只有几kb,便于传输 2.使用dockerfile构建出来的镜 ...
- Docker系列(三)Dockerfile 离线构建镜像
一.Dockfile介绍: Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令.Docker程序将这些Dockerfil ...
- Dockerfile减少构建镜像大小的方法
这几天基于Dockerfile构建应用需要的特殊的镜像,比如Nginx需要add很多module的,就需要在镜像内编译和做build. 通过Dockerfile构建镜像时,很容易把镜像构建得很大. 从 ...
- 013、Dockerfile构建镜像(2019-01-02 周三)
参考https://www.cnblogs.com/CloudMan6/p/6830067.html Dockerfile构建镜像过程分析 root@docker-lab:~/111# ls ...
- Dockerfile制作自定义镜像
本文介绍最精简的Dockerfile文件构建镜像,Docker启动的时候可以启动一个shell脚本 1.首先编写Dockerfile文件 说明 1.启动的这个shell脚本一定是不退出的,比如服务器的 ...
- Docker、Dockerfile、Docker镜像、容器这些都是什么鸟?
老生常谈,再再再……普及一下: Docker:最早是dotCloud公司出品的一套容器管理工具,但后来Docker慢慢火起来了,连公司名字都从dotCloud改成Docker. Dockerfile: ...
- docker学习笔记(2) 构建镜像
一.手动构建一个简单镜像 我们以构建nginx的docker镜像为例:手动构建镜像 docker pull centos 安装基础镜像docker run --name mynginx -it ...
- Dockerfile 构建镜像 - 每天5分钟玩转容器技术(13)
Dockerfile 是一个文本文件,记录了镜像构建的所有步骤. 第一个 Dockerfile 用 Dockerfile 创建上节的 ubuntu-with-vi,其内容则为: 下面我们运行 dock ...
- 使用Dockerfile构建镜像-Docker for Web Developers(5)
1.理解Dockerfile语法 语法命令 命令功能 举例 FROM 所有的dockerfile都必须以FROM命令指定镜像基于哪个基础镜像来制作 FROM ubuntu:14:04 MAINTAIN ...
随机推荐
- Python 面向对象的特性2-----继承
面向对象的三大特性 1.封装 根据职责将属性和方法封装到一个抽象的类中,然后类创建一个实实在在的对象,有了对象以后,就可以访问到对象内部的属性,或者让对象来调用一个已经封装好的方法. 2.继承 实现代 ...
- CentOS 7.0下安装Python3.6
CentOS 7.0自带Python2.7 安装Python3.6步骤 1.安装依赖 yum install -y zlib-devel bzip2-devel openssl-devel ncurs ...
- Ubuntu下 MySQL的“ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)”
今天闲来无事,在Ubuntu上掏鼓一下mysql.但尴尬的是,当我输入mysql -u root -p的时候,抛出了一个错误:ERROR 1045 (28000): Access denied for ...
- June 17. 2018, Week 25th. Sunday
Dad is and always will be my living, breathing superhero. 在我眼里,爸爸是现实版的超级英雄,现在.将来,永远都是. From Bindi Ir ...
- js中split()方法得到的数组长度
js 中split(",")方法通过 ”,“ 分割字符串, 如果字符串中没有 “,” , 返回的是字符串本身 var str = “abc”://分隔符个数为0 var newSt ...
- 《Java大学教程》—第10章 图形和事件驱动程序
10.2 Swing程序包AWT(Abstract Window Toolkit): 抽象窗口工具集.依赖于本地操作系统的组件被称为重量级(Heavy Weight)组件,因为它们都会大量使用系统资源 ...
- 【汤鸿鑫 3D太极】肩与膀的细分
- ASP.Net在64位环境开发部署常见问题
越来越多的开发团队開始使用64位操作系统作为开发环境,也计划将应用部署在安装有64位操作系统的server上.对于ASP.Net开发人员来说.使用64位环境开发部署须要注意下面几个问题.可在项目过程中 ...
- Python之TabError: inconsistent use of tabs and spaces in indentation和ModuleNotFoundError:No module named 'win32api'
1.TabError: inconsistent use of tabs and spaces in indentation 这是我的代码,感觉没啥不对, 后来运行之后出现了下面的错误,我也是弄了好久 ...
- 【ES6】=>含义
=>是es6语法中的arrow function (x) => x + 6 相当于 function(x){ return x + 6; }; var ids = this.sels.ma ...