所在位置:

Dockfile创建自定义镜像及数据卷的应用

能够使用Dockfile创建自定义镜像及数据卷的应用,就已经可以搭建一些的简单的服务了,下面先说一下概念的东西,然后再举一些例子,在上一篇文章说过,镜像是容器的基础,每次执行 docker run 的时候都会指定哪个镜像作为容器运行的基础。但是从 Docker Hub 里下载的镜像不一定满足我们的需求,这里我们就可以以已经有的镜像为基础来构建新的镜像,构建新的镜像有两种方法:

可以使用 docker commit 来构建新的镜像( 不建议这样做 )

镜像是多层存储,每一层是在前一层的基础上进行的修改;而容器同样也是多层存储,是在以镜像为基础层,在其基础上加一层作为容器运行时的存储层,所以我们可以修改容器的里面的内容,然后利用 docker commit 命令构建一个新的镜像,下面是一个简单的例子:

进入到 ubuntu 容器的命令行
docker run --name vimserver -it ubuntu /bin/bash
安装 vim
apt-get update
apt-get install -y vim
构建新的镜像

可以利用 docker commit 命令在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像,格式如下:

docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]

在这个例子里,我们把安装了 vim 的容器保存为镜像,命令如下:

docker commit --author "admin@163.com" --message "添加了vim" vimserver dockertest/ubuntu_vim

注意: dockertest 是已经注册仓库的用户名

可以使用 docker images 来查看是否已经生成了一个 dockertest/ubuntu_vim 的镜像

使用新的镜像

先清除之前已经运行的容器

docker stop $(docker ps -a -q)
docker container prune

再运行新的镜像

docker run --name vimserver -it dockertest/ubuntu_vim /bin/bash

在命令里运行 vim,看是不是已经成功了

慎用 docker commit

使用 docker commit 命令虽然可以比较直观的帮助理解镜像分层存储的概念,但是实际环境中并不会这样使用。使用 docker commit 意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为黑箱镜像,换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体在操作的,所以最好是使用 Dockerfile 来构建新的镜像

使用 Dockerfile 来构建新的镜像

1. 使用 Dockerfile 文件来构建镜像,下面是一些常用指令:

FROM

这个指令主要是指定基础镜像,在 DockerfileFROM 是必备的指令,并且必须是 第一条指令

常用的基础镜像有:

  • nginx
  • redis
  • mongo
  • mysql
  • httpd
  • php
  • tomcat
  • python
  • ruby
  • ubuntu
  • debian
  • centos
  • fedora
  • alpine
RUN

RUN指令是用来执行命令行的,有两种写法:

  • RUN <命令>

  • RUN ["可执行命令", "参数1", "参数2"]

CMD

CMD跟RUN指令差不多,也有两种写法:

  • CMD <命令>

  • CMD ["可执行命令", "参数1", "参数2"]

COPY

COPY指令是用来复制文件的,有两个写法:

  • COPY <源路径>... <目标路径>

  • COPY ["<源路径1>",... "<目标路径>"]

ADD

ADD是用来添加文件的,其实跟COPY差不多的,但是在添加压缩文件时,需要添加文件的同时还能自动解压缩的,就要用 ADD 指令,格式为:

  • ADD <源路径>... <目标路径>
ENTRYPOINT

ENTRYPOINT指令指定容器启动程序及参数,格式为:

ENTRYPOINT <命令>

ENV

ENV用来设置环境变量,格式有两种:

  • ENV <变量名> <变量值>

  • ENV <变量名1>=<变量值1> <变量名2>=<变量值2>...

VOLUME

VOLUME 定义匿名卷,格式为:

  • VOLUME ["<路径1>", "<路径2>"...]
  • VOLUME <路径>
EXPOSE

格式为 EXPOSE <端口1> [<端口2>...]

EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务

要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。-p,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射

WORKDIR

WORKDIR 指定工作目录,格式为 WORKDIR <工作目录路径>。

使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。

USER

USER 指定当前用户,格式:USER <用户名>

2. 使用Dockerfile构建gunicorn运行flask

第一步

新建目录

cd /home
mkdir -p gunicorn_demo/flask_demo
第二步

在 gunicorn_demo 目录下建立 Dockerfile 文件,内容如下

FROM ubuntu
RUN sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
RUN apt-get update && apt-get -y install python-pip \
&& pip install flask \
&& pip install gunicorn

ADD gunicorn.py /gunicorn.py

EXPOSE 8000

ENTRYPOINT ["/usr/local/bin/gunicorn", "--config", "/gunicorn.py"]
CMD ["app:app"]
第三步

在 gunicorn_demo 目录下新建一个 gunicorn.py 文件,内容如下

bind = '0.0.0.0:8000'
chdir = '/flask_demo'
workers = 2
第四步

在 flask_demo 目录下新建 app.py 文件,内容如下

#!/usr/bin/env python
# -*- coding: utf-8 -*-


from flask import Flask
app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'Hello, World!'


if __name__ == '__main__':
    app.run()
第四步

开始构建镜像

cd /home/gunicorn_demo
docker build -t="dockertest/ubuntu_gunicorn" .

这时用 docker images 命令可以的看到 dockertest/ubuntu_gunicorn 镜像了

测试镜像

可以使用下面命令运行镜像,把 本地的flask_demo目录 挂载到 容器的flask_demo目录

docker run --name webserver -v /home/gunicorn_demo/flask_demo:/flask_demo -p 8000:8000 -d docker1314/gunicorn_demo

在浏览器上运行 localhost:8000,应该可以看到效果了

数据卷

数据卷的几个特性:
  • 数据卷可以在容器之间共享和重用

  • 对数据卷的修改会立马生效

  • 对数据卷的更新,不会影响镜像

  • 数据卷默认会一直存在,即使容器被删除

举例

使用 v 参数,把本地的目录挂载到容器的目录里

docker run -it --name -v /home/docker/test:/test webserver ubuntu /bin/bash

使用 mount 参数,把本地的目录挂载到容器的目录里

docker run -it --name webserver --mount type=bind,source=/home/docker/test,target=/test ubuntu /bin/bash

【上一篇】docker的基础知识及安装

【下一篇】Docker Compose的用法