部署篇开头以两个简单的例子快速入门,然后介绍 Dockerfile 的常用命令
简单的例子
以下使用两个例子快速入题
官网的例子
这是来自 Docker 官方文档的例子,例子中使用了 Python,但不需要 Python 知识
使用 Dockerfile 生成容器
Docker 使用 Dockerfile
来生成容器。Dockerfile 会自动装配所用到的环境,所以你唯一需要做的就是敲几行命令。
Dockerfile
在任意文件夹下创建一个 Dockerfile
,把下面的代码复制进去。
# 使用 Python 官方运行环境作为一个父镜像
FROM python:2.7-slim
# 将工作目录设置为 /app
WORKDIR /app
# 把当前目录下的内容复制到位于 /app 下的容器中
ADD . /app
# 安装所有在 requirements.txt 中列出的所需要的包
RUN pip install --trusted-host pypi.python.org -r requirements.txt
# 向外界开放使容器的 80 端口
EXPOSE 80
# 定义环境变量
ENV NAME World
# 容器装配好之后运行
CMD ["python", "app.py"]
上面的 Dockerfile 需要 app.py
和 requirements.txt
两个文件,我们继续创建
requirements.txt
Flask
Redis
app.py
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)
现在执行下面的命令,生成一个镜像,-t
参数后的是镜像名,最后的 .
表示当路径
docker build -t friendlyhello .
使用以下命令查看所有镜像,命令 docker images
与其作用相同
$ docker image ls
REPOSITORY TAG IMAGE ID
friendlyhello latest 326387cea398
☪使用 Linux 的同学可能会遇到网络的问题
以下是官网文档的简单的翻译。博主不精通此问题,如有其他需要,请自行百度、Bing、Google…
DNS设置
如果使用了代理服务器,需要使用ENV
命令开启 host 的 portENV http_proxy host:port ENV https_proxy host:port
代理服务器设置
DNS 的错误配置会导致pip
的问题,可以使用自己的 DNS 服务器地址使pip
正常工作。通过编辑/etc/docker/daemon.json
,像下面这样{"dns": ["your_dns_address", "8.8.8.8"]}
RUN
使用以下命令来运行刚才创建好的镜像,-d
参数使其在后台运行,-p
参数使容器的 80 端口映射到主机的 4000 端口
docker run -d -p 4000:80 friendlyhello
访问 4000 端口 localhost:4000
,如果 Docker 在其他服务器上,将 localhost 改为服务器 IP 即可。如果之前的一切顺利,你应该会看到久违的 “Hello World”
然后,使用以下的命令可以查看所有正在运行的容器。命令 docker ps
与其作用相同
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED
1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago
书上的例子
这是周立所著 《Spring Cloud与Docker 微服务架构实战》一书中的例子。从篇幅就看到,这个例子更加简单一点
使用 Dockerfile 创建容器
和上面例子相同,首先创建一个 Dockerfile
FROM nginx
RUN echo '<h1> Hello World!</h1>' > /usr/share/nginx/html/index.html
在 Dockerfile
所在路径执行以下构建镜像的命令, :
为新镜像的标签, .
表示当前路径
docker build -t nginx:my .
添加标签页可由单独的命令 docker tag image name:tag
完成。以上面的例子为例:docker tag friendlyhello jackson:v_1
运行
执行启动 Docker 容器的命令
docker run -d -p 92:80 nginx:my
访问宿主机 92 端口,例如 123.206.98.122:92
,可以看到 “Hello World”
Dockerfile 常用命令
上面两个例子中用到了 FROM
,RUN
等命令,事实上,Dockerfile 有十多条指令。指令的一般格式为:指令名称 参数
ADD
复制文件
ADD <src> ... <dest>
ADD ["<src>",... "dest"]
从 src
目录复制文件到容器 dest
。src
可以是 Dockerfile
所在目录的相对路径,也可以是一个 URL
,还可以是一个压缩包
注意:
- src 必须在构建的上下文中,不能使用例如:ADD ../something/something/ 这样的命令
-
dest
不以/
结尾视作文件,否则视作目录 -
src
如果是URL
,其对应内容将被下载到dest
,若src
是一个目录,整个目录下的内容都将被复制。如果文件是可识别的压缩包,则docker
将会自动解压
示例:
ADD hello.jar app.jar
ARG
设置构建参数ARG
指令用于设置构建参数,类似于ENV
。和ENV
不同的是,ARG
设置的是构建时的环境变量,在容器运行时是不会存在这些变量的。
示例:
ARG use1=someuser
CMD
启动容器
每个Dockerfile
只有一个CMD
命令,如果指定了多个CMD
,则执行最后一条。有 3 种格式
-
CMD ["executable","param1","param2"]
(推荐) -
CMD ["param1","param2"]
(为 ENTRYPOINT 指令提供预设参数) -
CMD command param1 param2
(在 Shell 中执行)
示例:
CMD echo "This is a test." | wc -
COPY
复制文件
ADD <src> ... <dest>
ADD ["<src>",... "dest"]
复制 src
到容器的 dest
,和 ADD
命令类似。不同的是 COPY
指令不支持 URL
和压缩包
ENTRYPOINT
入口点
ENTRYPOINT ["executable","param1","param2"]
ENTRYPOINT command param1 param2
ENTRYPOINT
和 CMD
指令目的相同
ENV
设置环境变量
ENV <key> <value>
ENV <key>=<value> ...
示例:
ENV JAVA_HOME /path/to/java
EXPOSE
声明暴露的端口EXPOSE
声明用于声明在运行时容器提供服务的端口,格式为 :EXPOSE <port> [<port>...]
这只是一个声明,运行时并不会因为一个声明打开端口。该指令的作用主要是帮助镜像使用者理解该镜像服务的守护端口;其次是当运行时使用随机映射时,会自动映射EXPOSE
的端口。
示例:
# 声明暴露一个端口示例
EXPOSE port1
# 相应的运行容器使用的命令
docker run -p port1 image
# 也可以使用 -P 选项启动
docker run -P image
# 声明暴露多个端口示例
EXPOSE port1 port2
# 相应的运行容器使用的命令
docker run -p port1 -p port2 image
# 也可以指定需要映射到宿主机上的端口号
docker run -p host_port1:port1 -p host_port2:port2 image
FROM
指定基础镜像
使用FROM
指定基础镜像,有点像Java
中的extends
关键字。FROM
指令必须指定且要在其他指令之前。FROM
指令过后的所有指令都依赖于该指令所指定的镜像。支持 3 种格式:
FROM <image>
FROM <image>:<tag>
FROM <image>@<digeset>
LABEL
为镜像添加元数据
格式为:LABEL <key>=<value> <key>=<value>...
使用\
换行。示例:
LABEL version="1.0"
LABEL description="This is a \
test text"
MAINTAINER
指定维护者的信息
这个指令用于为Dockerfile
署名
示例:
MAINTAINER Cloudy<itsclody.gitee.io/blog>
RUN
执行命令
RUN <command>
RUN ["executable","param1","param2"]
RUN <command>
在 shell 终端中运行,在 Linux 中默认是 /bin/sh -c
,在 Windows 中是 cmd /s /c
,使用这种格式,就像直接在命令行中输入命令一样。
RUN ["executable","param1","param2"]
使用 exec 执行,这种方式类似于函数调用。指定其他终端可以通过该方式操作,例如:RUN ["/bin/bash","-c","echo hello"]
,该方式必须使用双引号 "
,而不能使用 '
,因为该方式会被转换成一个 JSON 数组
USER
设置用户
这个指令设置启动镜像时的用户或UID,写在该指令后的
RUN
、CMD
以及ENTRYPOINT
指令都将使用该用户执行命令
示例:
USER daemon
VOLUME
指定挂载点
这个指令使容器中的一个目录具有持久化储存的功能,该目录可被容器本身使用,也可共享给其他容器。当容器中的应用有持久化数据的需求时可以在 Dockerfile 中使用该指令。格式为:VOLUME ["/data"]
示例:
VOLUME /data
WORKDIR
指定工作目录
格式为:WORKDIR /path/to/workdir
写在该命令之后的RUN
、CMD
以及ENTRYPOINT
指令都将该目录作为当前目录,并执行响应的操作- 其他
其他命令并不常用,不在赘述。有兴趣请前往官网文档扩展。
后记
借鉴《Spring Cloud与Docker微服务架构实战》/周立 著