在介绍 Docker 具体的操做前,先简要复习下 Docker 的架构,这样能够更好地帮助咱们理解 Docker 中的各个命令。html
首先咱们一直对 Docker 这个叫法就有些误解,Docker 其实指代的是用于开发,部署,运行应用的一个平台。日常中说的 Docker 准确来讲是 Docker Engine.python
Docker Engine 是一个 C/S 架构的应用。其中主要的组件有:git
咱们经过给 Docker Client 下发各类指令,而后 Client 经过 Docker daemon 提供的 REST API 接口进行交互,来让 daemon 处理编译,运行,部署容器的繁重工做。 大多数状况下, Docker Client 和 Docker Daemon 运行在同一个系统下,但有时也可使用 Docker Client 来链接远程的 Docker Daemon 进程,也就是远程的 Server 端。docker
清楚了 Docker 的简单架构,就能够了解下具体的命令了。shell
docker build [OPTIONS] PATH | URL | -
Docker 构建镜像的上下文。数据库
这里的上下文指的就是命令的最后一个参数 PATH | URL| -
,具体来讲就 docker build .
中的 .
不少人觉得这个 .
是 DockerFile 的位置,其实否则,准确来讲是构建上下文的位置。前面说到 Docker 是 C/S 架构,在 Client 端下发具体的命令,在 Server 端(Daemon)执行具体的内容。这也就意味着,构建镜像的过程实际上是在 Server 端完成的。而上下文的出现,就是为了把须要的内容传递给 Server,这也就为何在每次构建时都能看到这样一句话。centos
[root@localhost python_shell]# docker build --rm -t temp/python-test . Sending build context to Docker daemon 4.608kB
这里的 Sending 其实就是把本地 Client 端的文件内容,拷贝到 Server 端。而许多初学者,在 DockerFile 中写出了 COPY /opt/xxxx /app
这样的话,其实就是没有理解上下文的概念,并不知道在 Server 端是没有 opt/xxxx
的文件的。缓存
还有的人将 Docker File 放在硬盘根目录执行,却不知,这样会将根目录全部的文件都拷贝到 Server 端,形成构建极其缓慢。服务器
Options 经常使用参数:网络
-t
: 打包出镜像的名称及标签,一般写法为 name:tag
--rm
: 构建成功后,删除中间产生的容器。--force-rm=true
: 不管是否构建成功,都删除中间产生的容器--no-cache
: 构建镜像时不使用缓存。-f
: 指定 DockerFile 的路径docker build --no-cache --force-rm -t --no-cache local/centos7:v1 .
经过 FROM
来制定基础镜像,命令很简单,但有一点须要注意的是,必定确切指定基础镜像的版本,而不是写成 latesst
, 由于随着时间推移,官方的最新镜像都会一直更新,这样就会形成没法构建的状况。
FROM centos:7 # That's perfect! FROM centos:latest # That's so bad!
RUN 命令用于在容器中执行命令行的命令。通常有两种写法:
RUN 后面直接跟 shell 命令就能够了。切记,在 shell 形式下,不要把命令拆成多行 RUN。由于每一次的 RUN 都会构建一层新的镜像,保存了不少没有用的运行信息。并且 Union FS 是由最大层数限制的。因此尽可能将命令合成一行。
RUN yum -y install httpd; yum clean all; systemctl enable httpd.service # That's perfect! RUM yum -y install httpd / # Another perfect solution! yum clean all / systemctl enable httpd.service RUN yum -y install httpd # That's so bad! RUN yum clean all; ....
还有一点须要注意,把构建时没用的依赖包想着清空。不然的话,随着镜像的重复构建,保存了大量的没有信息。
exec 写法更像函数调用中的格式。
RUN ["可执行文件", "参数1", "参数2"] RUN ["yum", "-y", "install", "httpd"]
WORKDIR 用于改变各层的工做目录(也就是进入容器内的默认目录),若是指定的目录不存在就会建立它。工做目录在构建过程当中,能够被各层都访问到。
WORKDIR /src
在容器运行时,尽可能对容器的存储层不进行写操做,对于像数据库中这样动态的数据文件应该用 VOLUME 来保存。而在 DockerFile VOLUME 能够将目录指定为匿名卷。这样在运行时,若是没有挂载指定的目录,并不会像容器的存储层写入数据,保证存储层的无状态化。
VOLUME /data
官方 Centos7 的镜像已经包含了 systemd 的功能,只是没有开启。这里只须要以其为基础镜像,打开 systemd 的功能便可。须要注意的是,打开 systemd 须要在运行时开启特权以挂载 Cgroup 等内容。
编写 DockerFile
[root@localhost docker_images]# cat Dockerfile FROM centos:7 ENV container docker RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \ systemd-tmpfiles-setup.service ] || rm -f $i; done); \ rm -f /lib/systemd/system/multi-user.target.wants/*;\ rm -f /etc/systemd/system/*.wants/*;\ rm -f /lib/systemd/system/local-fs.target.wants/*; \ rm -f /lib/systemd/system/sockets.target.wants/*udev*; \ rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \ rm -f /lib/systemd/system/basic.target.wants/*;\ rm -f /lib/systemd/system/anaconda.target.wants/*; VOLUME [ "/sys/fs/cgroup" ] CMD ["/usr/sbin/init"]
打包镜像
docker build --rm -t local/c7-systemd .
运行镜像
docker run --privileged=true -ti -v /sys/fs/cgroup:/sys/fs/cgroup:ro local/c7-systemd
下面基于上面开启 systemd 的镜像为基础,打包 Httpd 镜像。
编写 DockerFile
FROM local/c7-systemd RUN yum -y install httpd; yum clean all; systemctl enable httpd.service EXPOSE 80
编译 DockerFile
docker build --rm -t local/c7-systemd-httpd .
运行 Container
docker run --privileged=true -ti -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ -p 80:80 local/c7-systemd-httpd
在下载依赖时出现网络问题,请查看 Docker 代理 这篇文章。
有时咱们须要在容器中运行 python 脚本,下面来打包相似的镜像。在下载须要的依赖时,一般的服务器并没访问公网的能力,这时须要为容器配置配置代理,在下载依赖后,有时因为代理的缘由,致使内部的服务器没法访问,这时能够再将设置的代理清空。
建立文件
注意,这里的文件要和 DockerFile 在同级目录下。
# 建立 requirements 文件保存依赖 [root@localhost home]# cat python_shell/requirements.txt requests==2.21.0 # 编写 Python 脚本 [root@localhost home]# cat python_shell/success.py print("python Running", "!");
编写 DockerFile
FROM python:3.6.8 # set proxy ENV MY_PROXY_URL="http://173.39.112.117:80" ENV HTTP_PROXY=$MY_PROXY_URL \ HTTPS_PROXY=$MY_PROXY_URL \ FTP_PROXY=$MY_PROXY_URL \ http_proxy=$MY_PROXY_URL \ https_proxy=$MY_PROXY_URL \ ftp_proxy=$MY_PROXY_URL WORKDIR /src COPY . . RUN ["pip", "install", "--no-cache-dir", "-r", "./requirements.txt"] # clear the proxy ENV MY_PROXY_URL= ENV HTTP_PROXY=$MY_PROXY_URL \ HTTPS_PROXY=$MY_PROXY_URL \ FTP_PROXY=$MY_PROXY_URL \ http_proxy=$MY_PROXY_URL \ https_proxy=$MY_PROXY_URL \ ftp_proxy=$MY_PROXY_URL CMD ["python", "./success.py"]
打包镜像
docker build --rm -t temp/python-test .
运行镜像
[root@localhost home]# docker run temp/python-test python Running !
https://blog.fundebug.com/2017/05/15/write-excellent-dockerfile/