我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

如何从零开始,制作一个docker镜像呢?如果可以自定义一个docker镜像,就可以封装自己想要的功能和版本。这个是一件令人振奋的事情。那么,本文中,苏南大叔介绍的就是:如何定义并使用Dockerfile文件,并最终封装一个docker镜像。

本文中,所使用的具体代码例子,来源自网络。镜像的具体的功用是:安装一个基于python的框架flask,对外提供www服务。这个例子,在网络上还是很流行的。苏南大叔就根据自己的理解,对这个例子进行一下解读。

苏南大叔:如何利用Dockerfile,从零开始制作一个docker镜像? - docker-hero
如何利用Dockerfile,从零开始制作一个docker镜像?(图3-1)

整个套路是这样的:新建一个Dockerfile文件。在文件里,定义编写特定的功能脚本。最后在当前目录下面,执行命令docker build -t <imgname> .,就可以得到一个自定义的docker镜像了。

本文的测试环境是:centos7.5docker 18.06.1-ce, build e68fc7a

Dockerfile内容

首先,苏南大叔在测试机,新建一个文件夹test,作为本次镜像制作的工作目录。test目录里面,放置一个名为Dockerfile的文件,注意:不能改名,注意大小写。

Dockerfile内容如下:

# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
ADD . /app

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

参数说明From

在上述范例中,需要特别注意的就是:From
From,指的是:基础镜像。一般来说设置为centos:latest
我们要设置的基础镜像,我们可以使用docker search找到基本镜像名称。然后,通过选中的镜像名称,查找相关的tags。查找到合适的tag,就可以继续继续了。

具体可以参见这篇文章:

  • 《如何查找特定功能的docker镜像?docker镜像hub地址大全》

https://newsn.net/say/docker-search.html

参数说明WORKDIR

WORKDIR,苏南大叔这边理解着就是:类似于大家常见的cd命令。在执行后续的构建命令的时候,需要先切换到某个目录中,那么这个WORKDIR,就起到了cd的作用。那么因此,路径中的斜线之类的都会是有特殊意义的,多次WORKDIR,路径间也是有相互作用的。anyway,大家把它理解为cd,就很好说明一切问题了。

同时,这个参数,还可以影响容器命令行的默认目录。正常情况下来说,通过docker exec <name> /bin/bash进入容器内部的时候,默认所处的目录,就是这个WORKDIR目录。

WORKDIR目录,存在于镜像(容器)内部,与宿主机无关。

参数说明ADD

ADD命令两个参数,ADD <source> <dest>。苏南大叔把这个ADD命令,就理解为cp命令。就是复制文件的意思,把制作镜像时的宿主机上的某些文件或目录,复制到镜像内部的某个位置上去。这些文件,一般都是未来可能会在镜像里面,用到的特殊文件。

在本例中,在执行docker build命令之前,宿主机的test目录下面,所有的文件,都会被无差别的复制到镜像的/app目录下面。所以,那些文件,需要被复制到镜像里面呢?大家可以先想好,再执行build。比如Dockerfile文件,其实就并不需要复制到镜像里面。

参数说明RUN

RUN命令,就是常理上的执行某条命令。本例子中,就是利用pip安装了一些依赖包,特殊的地方,就是依赖包列表是放在了requirements.txt文件里面了。这里不做详细解释。更多详细内容,大家可以参见苏南大叔的pip相关经验链接。

在本例中,requirement.txt对于Dockerfile并不是必须的,只是本次实验的一个普通文件。内容如下:

Flask
Redis

RUN就是镜像构建时的CMD命令,但是RUNCMD还是有比较重大的区别的,这里做个伏笔。作为小白入门教程,这里的RUN就简单理解为执行某条命令即可。

参数说明CMD

RUN基本上一致,只是CMD是构建好镜像之后,运行镜像的时候,才执行的。在写法上,CMD也可以不使用这种数组的形式,具体请参见未来的经验文章。在功用上,CMDENTRYPOINT是很类似的。这里,苏南大叔就简要的说一句,CMDdocker run -it的时候,可以被覆盖的。而ENTRYPOINT则不会被覆盖。就是说,ENTRYPOINT,恒定会执行的。

参数说明EXPOSE

EXPOSE英文单词,就是暴露的意思,就是说,对外提供一个什么样的端口号。就相当于docker run时,-p <port1>:<port2>中的port2,这个比较好理解。需要暴露多个端口号的时候,就写很多行的EXPOSE语句即可。

EXPOSE 80
EXPOSE 81
EXPOSE 82
# ...

入口文件app.py

这个app.py,就是基于pythonwww脚本。这里涉及的python脚本的用法,苏南大叔就不具体解释了。因为,和本文的主要议题docker的镜像制作,关系不大。

至是需要说明的是:这个入口文件,可以用于接收环境变量。也就是docker run时的-e参数。这个环境变量,还可以在Dockerfile里面使用ENV命令,设置默认值。

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>" \
           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {visits}"
    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

构建docker镜像

苏南大叔使用docker build命令,来构建最终的docker镜像。构建的依据就是:Dockerfile文件。使用-t来定义镜像名称,.表示要操作的目录。

docker build -t test .

苏南大叔:如何利用Dockerfile,从零开始制作一个docker镜像? - docker-build
如何利用Dockerfile,从零开始制作一个docker镜像?(图3-2)

那么,上述命令,就把上述Dockerfile文件构建成了,一个带有www功能的镜像,名字为test

运行镜像为容器

得到了test镜像之后,就可以docker run了。这里,苏南大叔也不做详细解释了。下面是个docker run的命令范例。

docker run --name test2 -p 4000:80 -e NAME=sunan -d test

大家,可以仔细想想-p-e参数,是怎么来的。对比一下Dockerfile里面的相关参数,来加深一下印象。

苏南大叔:如何利用Dockerfile,从零开始制作一个docker镜像? - docker-images-www
如何利用Dockerfile,从零开始制作一个docker镜像?(图3-3)

总结

本文中,苏南大叔所叙述的Dockerfile,仅仅是冰山一角。里面还有很多不同的参数命令。更多Dockerfile的应用经验文字,请点击下面的链接查看。

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   python    docker