dockerfile用于构建docker镜像的,部署一个用于运行你所需的容器环境。相当一个脚本,通过dockerfile自己的指令,来构建软件依赖、文件依赖、存储、
定制docker镜像的方式有两种:
手动修改容器内容,导出新的镜像
基于Dockerfile自行编写指令,基于指令流程创建镜像。
dockerfile简介
镜像都是多层存储的,每一层在前一层的基础上进行修改:
容器也是多层存储,以镜像为基础层,在其基础上加一层做为容器运行时的存储层。
镜像的创建有两种方式:
1、手动修改容器内容,然后docker commit提交容器为新的镜像
2、通过在dockerfile中定义一系列的命令和参数构成的脚本,然后这些命令应用于基础镜像,依次添加层,最终生成一个新的镜像,极大的简化了部署工作。
dockerfile主要组成部分:
基础镜像信息FROM centos:6.8
制作镜像操作指令RUN yum install openssh-server -y
容器启动时执行指令 CMD ["/bin/bash"]
举例:
安装一个mysql,且启动
如果是虚拟机部署形式的话,如下
- 开启vmare
- 运行某一个虚拟机,centos7
- centos7 安装mysql ,yum install mysql-server
- 通过脚本,或者命令,启动mysql即可
部署缓慢,且修改了宿主机的环境,删除较为麻烦,占用宿主机的3306端口
下面是基于容器运行mysql
- 开始vmware
- 运行虚拟机centos7
- 安装docker容器软件
- 获取mysql镜像即可,docker pull mysql:tag(你无法自由控制,该mysql的镜像是什么发行版,你获取的镜像,是别人定制好的,你下载使用的,你希望得到一个基于centos7.8的发行版,运行mysql)
- 直接运行该镜像,通过端口映射,运行mysql,docker run mysql:5.6 (容器能够运行,必须在容器内,有一个进程在前台运行,该容器内,有mysql正在前台运行)。
- 访问宿主机的一个映射端口,访问到容器内的mysql
想自定义镜像,就得自己写脚本,也就是dockerfile
dockerfile指令
FROM 这个镜像的妈妈是谁?
MAINTAINER(指定维护者信息,可以没有)
RUN你想让它干啥(在命令前面加上RUN即可)
ADD添加宿主机的文件到容器内,还多了个自动解压的功能。
COPY 作用和ADD是一样的,都是拷贝宿主机的文件到容器内
WORKDIR (设置当前工作目录)
VOLUME 设置卷,挂在主机目录
EXPOSE 指定对外的端口,在容器内暴露一个端口
CMD,指定容器启动后的要干的事情
dockerfile实践
需求,通过dockerfile,构建nginx镜像,且运行容器后,生成的页面是,“测试”。
- 创建Dockerfile,注意文件名,必须是这个cat Dockerfile
FROM nginx
RUN echo '测试大佬' >
/usr/share/nginx/html/index.html
2、构建Dockerfile
docker build .
3、修改镜像名字
docker tag b4200a856253 my_nginx
4、运行该镜像
docker run -d -p 80:80 my_nginx
5、查看宿主机的80端口
COPY指令
copy指令从宿主机复制文件/目录到新的一层镜像内如
copy test.py /home/
支持多个文件,以及通配符形式复制,语法要满足Golang的filepath.Match
copy test* /tmp/cc?.txt. /home/
COPY指令能够保留源文件的元数据,如权限,访问时间等等。
ADD
特性和COPY基本一致,不过多些功能
- 源文件是一个url,此时docker引擎会下载该链接,放入目标路径,且权限自动设为600,若这不是期望结果,还得增加一层
- 源文件是一个url,且是一个压缩包,不会自动解压,也得是单独用RUN指令解压
- 源文件是一个压缩文件,且是gzip、bzip2、,ADD指令会自动解压缩文件到目标路径。
Dockerfile 官方推荐使用COPY,ADD会使构建缓存失效,导致镜像构建失败缓慢。
CMD在容器内运行某个命令,启动
用法,注意是双引号
CMD["参数1","参数2"]
在制定了entrypoint指令后,用CMD指令具体的参数
docker 不是虚拟机,容器就是一个进程,既然是进程那么程序在启动的时候需要制定运行参数,这就是CMD指令作用。
例如centos 镜像默认的CMD是/bin/bash,直接docker run -it centos 会直接进入bash解释器。
也可以启动容器时候,指定参数,docker run -it centos cat /etc/os-releasea
CMD运行shell 命令,也会被转化为shell形式
例如
CMD echo $PATH
会被转化为
CMD ["sh", "-c","echo "]
容器内运行程序
这里需要注意,docker不是虚拟机的概念,虚拟机里的程序运行,基本上都是在后台运行,利用systemctl 运行,但是容器内没有后台进程的概念,必须前台运行。
容器就是为了主进程而存在的,主进程如果退出了,容器也就失去意义了,自动退出。
CMD systemctl start nginx
这种写法是错误的,容器会自动退出
因为 systemctl star nginx 是希望以守护进程形式启动nginx,且CMD命令会转化为
CMD ["sh","-c","systemctl start nginx"]
这样的命令主进程是sh解释器,执行完毕后立即结束了,因此容器也就退出了
因此正确的写法是CMD ["nginx","-g","daemon off;"]
ENTRYPOINT 和 CMD的区别及用法
ENTRYPOINT 和CMD的区别及用法
ENV和ARG都是给容器设置环境变量
区别在于ENV无论是在镜像构建时,还是容器运行时,该变量都可以使用
ARG只是用于构建镜像需要设置的变量,容器运行时就消失了。
VOLUME
容器再运行时,应该保证在存储层不写入任何数据,运行在容器内产生的数据,我们推荐是挂载,写入到宿主机上,进行维护。
VOLUME /data #将容器内的/data文件夹,在容器运行时,该目录自动挂载为匿名卷,任何向该目录中写入数据的操作,都不会被容器记录,保证的容器存储层无状态理念。
EXPOSE ,制定容器运行时对外提供的端口服务,
帮助使用该镜像的人,快速理解该容器的一个端口业务,
docker port 容器
docker run -p 宿主机端口:容器端口
docker run -p #作用是随机宿主机端口:容器内端口
WORKDIR
用于在dockerfile中,目录的切换,更改工作目录,
WORKDIR /opt
USER
用于改变环境,用于切换用户
USER root
USER test
构建一个网站镜像
- nginx,修改首页内容,html
- web framework ,web框架,一般由开发,通过某个开发语音,基于某个web框架,自己去开发一个web站点,python、django框架。
本次实践:
- 用python语言,基于flask web框架,开发一个网站,写一个后端的 网站代码
- 开发dockerfile,部署该代码,生成镜像
- 其他人基于该镜像,docker run就可以在电脑跑起来你这个网站
比如安装一个etcd、nacos,都是比较复杂的一些软件
需要依赖于go语言环境,比如需要依赖于java环境,在自己的机器安装好对应的开发环境,以及对应的版本,以及个各种依赖。
tomcat、jdk环境
当有了docker
docker pull nacos 打包好了各种依赖环境
docker pull tomcat 这些主流的镜像都可以直接找到,并且该镜像中,就已经打包好了Java环境
docker run tomcat xxxx 可以直接访问tomcat了
- 在宿主机上准备一个目录,准备好dockerfile
写一个flask 的python代码
创建好代码文件
- 编写dockerfile
touch Dockerfile
RUN curl -o /etc/ ;
RUN curl -o /etc/ ;
RUN yum makecache fast;
RUN yum install python3-devel python3-pip -y
RUN pip install flask
COPY test_flask.py /opt
WORKDIR /opt
EXPOSE 8080
CMD ["python","app.py"]
- 检查代码环境,及内容
代码文件 和 Dockerfile 在平级目录中
- 构建镜像
生成一个镜像
docker build -t 'test/my_flask' .
然后执行dockerfile里的命令
docker build --no-cache -t ‘test/my_flask’.
- 运行镜像,生成容器, -d 后台运行 --name 容器的名字 -p宿主机的90端口访问到容器内地8080
docker run -d my_flask -p 90:8080 test/my_flask
- 访问宿主机,看容器内flask web网站
- 如何修改该网站的内容
第一种修改宿主机的代码,以及dockerfile,重新构建
第二种可以进入到以及运行的容器内,修改代码,重启容器即可。
(1)进入容器
docker exec -it 容器id bash
(2)修改容器内的程序
cat test_flask.py
(3)退出容器,重启容器
exit
docker restart 容器id