Dockerfile指令(用于构建Docker镜像)
Dockerfile相当于一个脚本,通过dockerfile自己的指令,来构建软件依赖,文件依赖,存储依赖等。
创建镜像有两种方法:
1.手动修改容器内容,然后docker commit提交容器
2.通过在dockerfile中定义一系列的命令和参数构成的脚本,然后这些命令应用与基础镜像,依次添加层,最终行成一个新的镜像。极大的简化了部署工作。
官方提供的dockerfile实例:
https://github.com/CentOS-Dockerfiles
dockerfile主要组成部分:
基础镜像信息 FROM centos:6.8
制作镜像操作指令RUN yum install openssh-server-y
容器启动时执行指令CMD[“/bin/bash”]
dockerfile实践学习
需求:
安装一个MySQL,且启动
如果是虚拟机部署形式,如下:
1.开启虚拟机
2.centos安装MySQL
3.通过脚本,或者命令,启动MySQL
部署缓慢,且修改了宿主机的环境,删除较麻烦,占用宿主机的一个3306端口
基于容器去运行:
1.开启虚拟机
2.运行centos
3.安装docker容器软件
4.获取MySQL镜像,docker pull mysql(无法自由控制,该MySQL的基础镜像是什么发行版)
5.运行该镜像,通过端口映射,运行MySQL docker run MySQL
6.访问宿主机的一个映射端口,访问到容器内的MySQL
想自定义镜像,就需要自己写脚本(dockerfile)
1.常用指令
FROM 这个镜像的妈妈是谁? (指定基础镜像)
MAINTAINER 告诉别人,谁负责养他? (指定维护者信息,可以没有)
RUN 你想让它干嘛 (在命令前加RUN即可)
ADD 给它点创业资金
COPY文件,会自动解压(作用和ADD一样,将宿主机文件拷贝到容器,但ADD会自动解压)
WORKDIR 我是cd,我今天画了妆(设置当前工作目录)
VOLUME 给它一个存放行李的地方(设置卷,挂载主机目录)
EXPOSE 它要打开的门是啥 (指定对外的端口),在容器内暴露一个窗口,端口
CMD 奔跑吧,兄弟! (指定容器启动后需要做的事情)
2.其他指令
1.COPY 复制文件
2.ENV 环境变量
3.ENTRYPOINT 容器启动后执行的命令
实例:
需求:定制一个nginx
##创建一个目录
[root@localhost ~]# mkdir /learn_docker
[root@localhost ~]# cd /learn_docker/
##修改文件内容
[root@localhost learn_docker]# vim Dockerfile
[root@localhost learn_docker]# cat Dockerfile
FROM nginx
RUN echo '<meta charset=utf8>宇哥宇哥宇哥' > /usr/share/nginx/html/index.html
##构建镜像
[root@localhost learn_docker]# docker build .
[+] Building 0.2s (4/5) docker:default
[+] Building 0.3s (5/6) docker:default
[+] Building 0.3s (6/6) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 133B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/nginx:latest 0.0s => CACHED [1/2] FROM docker.io/library/nginx 0.0s => [2/2] RUN echo '<meta charset=utf8>宇哥宇哥宇哥' > /usr/share/n 0.2sxporting to image 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:438f6f8363e3d05eab74df6ed2347f956b25286e8fadf 0.0s
##查看镜像
[root@localhost learn_docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 438f6f8363e3 42 seconds ago 141MB
nginx latest 605c77e624dd 19 months ago 141MB
ubuntu latest ba6acccedd29 22 months ago 72.8MB
hello-world latest feb5d9fea6a5 23 months ago 13.3kB
##改名
[root@localhost learn_docker]# docker tag 438f6f8363e3 my_nginx
##查看镜像
[root@localhost learn_docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my_nginx latest 438f6f8363e3 11 minutes ago 141MB
nginx latest 605c77e624dd 19 months ago 141MB
ubuntu latest ba6acccedd29 22 months ago 72.8MB
hello-world latest feb5d9fea6a5 23 months ago 13.3kB
##运行镜像
[root@localhost learn_docker]# docker run -d -p 80:80 my_nginx
7259d01379e805f63fc9aee6d670a2b172ff1aebbb446b05277977943e59dc47
如下指令如何使用:
#COPY
copy 源文件目录 目标目录
#支持多个文件,以及通配符形式复制,语法要满足Golang的filepath.Match
#ADD
ADD 源文件目录 目标目录 (此命令支持url,可远程下载)
RUN Linux命令 (xxx修改命令)
#CMD在容器内运行某个命令
该镜像在运行容器实例的时候,执行的具体参数
CMD["参数1","参数2"]
CMD["/bin/bash"] #使用bash解释器
#该容器运时,执行的命令
#等同于命令行操作
CMD["cat",etc/os-release"]
3.容器内运行程序
CMD systemctl start nginx
这样的写法是错误的,容器会立即退出
因为systemctl start nginx 是希望以守护进程形式启动nginx,且CMD命令会转化为:
CMD ["sh","-c","systemctl start nginx"]
这样命令主进程是sh解释器,执行完毕后立即结束了,因此容器也就退出了
因此正确写法应该是CMD ["nginx","-g","daemon off;"]
ENTRYPOINT与CMD
ENTRYPOINT与CMD作用一样,都是在指定启动程序以及参数
当指定了ENTRYPOINT之后,CMD指令的语义就有了变化,而是吧CMD的内容当作参数传递给ENTRYPOINT指令。
#1.准备一个dockerfile
FROM centos:7.8.2003
RUN rpm --rebuilddb && yun install epel-release -y
RUN rpm --rebuilddb && yun install curl -y
CMD ["curl","-s","https://ipinfo.io/ip"]
#用法如下
docker run my_centos curl -s http://ipinfo.io/ip
#
docker run my_centos
#2.构建镜像
docker build .
#3.查看结果
[root@localhost learn_docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my_nginx latest 67d97fda1f56 50 minutes ago 141MB
nginx latest 605c77e624dd 19 months ago 141MB
centos latest 5d0da3dc9764 23 months ago 231MB
centos 7.8.2003 afb6fca791e0 3 years ago 203MB
<none> <none> e6ab6553d9a4 3 years ago 203MB
#改名
[root@localhost learn_docker]# docker tag 镜像ID my_centos
#4.检查镜像
docker images
#5.运行镜像,生成容器
[root@localhost learn_docker]# docker run cmd_text
210.21.12.76[root@localhost learn_docker]#
运行后只是访问https://ipinfo.io/ip 没有程序前台运行,执行完立刻退出容器
#6.上述运行正确,但想再次传入一个参数,如何操作
发现无法直接传入参数,该形式是覆盖镜像中的cmd
就好比吧docker镜像,当作一个环境,去执行后面的命令
[root@localhost learn_docker]# docker run my_centos -I **报错** 执行顺序为:curl -s -I
[root@localhost learn_docker]# docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-I": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container:
如果:docker run my_centos pwd
[root@localhost learn_docker]# docker run cmd_text pwd
/
可以执行pwd命令,但不执行cmd中的命令
说明后面的参数、会覆盖CMD中的命令
#7.若想给它传入参数,该怎么操作?使用 ENTRYPOINT
修改dockerfile如下:
FROM centos:7.8.2003
RUN rpm --rebuilddb && yun install epel-release -y
RUN rpm --rebuilddb && yun install curl -y
ENTRYPOINT CMD ["curl","-s","https://ipinfo.io/ip"]
#8.重新构建该镜像
[root@localhost learn_docker]# docker build .
[+] Building 0.0s (5/5) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 110B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/centos:7.8.2003 0.0s
=> CACHED [1/1] FROM docker.io/library/centos:7.8.2003 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:02fd41bb746fbb27aee730a8250f6fe327a899c18139fb11184ddb8d6961d8e 0.0s
#9.改名
[root@localhost learn_docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my_nginx latest 67d97fda1f56 2 hours ago 141MB
nginx latest 605c77e624dd 19 months ago 141MB
centos latest 5d0da3dc9764 23 months ago 231MB
entrypoint_test latest 02fd41bb746f 3 years ago 203MB
centos 7.8.2003 afb6fca791e0 3 years ago 203MB
cmd_text latest e6ab6553d9a4 3 years ago 203MB
#10.重新运行该镜像
docker run entrypoint_test -I
此时容器的完整执行顺序为:curl -s https://ipinfo.io/ip -I
ARG与ENV指令
设置环境变量
容器1 nginx
容器2 php-fpm
容器3 mysql
…
dcokerfile脚本、shell脚本
ENV NAME="xiaocao"
ENV AGE="18"
ENV MYSQL_VERSION=5.6
后续所有的操作,通过$NAME 就可以直接获取变量值了 更方便维护dockerfile脚本方便
ADD
COPY
EXPOSE
ARG与ENV一样 设置环境变量
区别在于
ENV 无论是在环境构建时,还是容器运行是,该变量都可以使用
ARG 只是用于构建镜像需要设置的变量,容器运行时就消失了
VOLUME
容器在运行是应该保证在存储层不写入任何数据,运行在容器内产生的数据,推荐是挂载,写入到宿主机上,进行维护
VOLUME /data #将容器内的/data文件夹,在容器运行时,该目录自动挂载为匿名卷,任何向该目录中写入数据的操作,都不会被容器记录,保证容器的容器存储层。
##Dockerfile
FROM centos
MAINTATINER cao
VOLIME ["/data1","/data2"]
该容器运行时,这两个目录自动和宿主机的目录做好映射关系
docker build .
#运行该镜像
docker run ID
#查看容器生成信息
docker inxpect ID 可以看到挂载信息
1.容器数据挂载的方式,通过dockerfile,指定VOLUME目录
2.通过docker run -v 参数,直接设置需要映射挂载的目录
EXPOSE
用于指定容器运行时对外提供的端口服务
帮助使用该镜像的人,快速理解该容器的一个端口业务
docker port 容器
docker run -p 宿主机端口:容器端口
docker run -p #作用是随机宿主机端口:容器端口
WORKDIR
用于在dockerfile中,目录的切换,更改工作目录
WORKDIE /opt
USER
用于改变环境,用于切换环境
USER root
USER cao
后面为操作用户