自学Python第二十七天- 部署极简生产环境,使用windows、linux、docker环境


当写好的 python 脚本需要部署到服务器时,可能不希望安装一堆支持库、编辑环境等,最好是使用一个绿色的极简环境进行部署。使用 windows 桌面版系统的多一些,也可以使用 linux 系统部署。

Windows 环境部署

windows 环境下可以制作一个绿色编写式 python 环境用于快速执行脚本,也可以进行绿色部署

创建绿色 python 环境

首先去Python官网上下载嵌入版本的python:

python官网下载地址

在此链接根据需要的 python 版本,下载 embeddable package 即可(注意CPU架构)

解压后在其中我们创建一些文件方便我们的使用和配置:

  • 创建一个配置环境变量设置批处理文件python_env.bat,免除每次手动设置环境变量的麻烦(需要注意的是,python_env.bat 和其他解压文件放在一起)
@echo off
# 如果此批处理文件没有和python文件在同一目录下,则需要使用DOS命令进入该目录
# cd python
set PYTHON_HOME=%cd%
set PATH=%PYTHON_HOME%;%PYTHON_HOME%\Scripts;%PATH%
@echo on
  • 创建一个快捷方式,免除每次需要打开cmd后手动执行批处理文件设置环境变量的麻烦(和 python.bat 放在同一目录下)
    在这里插入图片描述
    配置完成后可以运行快捷方式,并通过执行下面脚本检查以快捷方式打开的环境的python是否是我们的精简绿色环境:
Python 
import sys 
print(sys.path)

然后如果需要,可以额外安装 pipy:

https://pypi.org/project/pip/ 下载get-pip.py

pypi上的 get-pip.py 下载链接

执行下面的命令安装pip

python.exe get-pip.py

然后需要修改*._pth文件
以python3.8.10为例,修改python38._pth文件,取消import site前的注释后保存

python38.zip
.

# Uncomment to run site.main() automatically
import site # 取消这里的注释

可以更新 pip

python.exe -m pip install --upgrade pip

至此,一个绿色精简的python环境就配置好了,通过我们创建的快捷方式打开后就可以像普通python环境一样安装所需的库了。

注:环境变量只在快捷方式打开的窗口内有效,所以要执行脚本也最好使用此窗口。

Linux 环境部署

由于目前暂时没有 Linux 系统的服务器,所以使用了 win11 + Linux 子系统搭建 Linux 环境,也可以使用 VMware 制作虚拟机。

创建 Linux 环境

使用Hyper-V

要在Windows 11下使用Linux子系统,需要启用Hyper-V和Linux子系统功能。

打开设置->应用->可选功能->更多Windows功能,把Hyper-V适用于Linux的Windows子系统打上勾,子项目全选,点确定,安装完重启。如果可以,多分配一两个CPU核心给虚拟机,不然会影响Linux子系统的安装与运行。

重启完成后,先更新wsl,不然可能会报错,wslregisterdistribution failed with error: 0x80370109,类似这样的,错误码有好几个。

wsl --update

然后安装 Linux 分发版,以Ubuntu为例

wsl --install -d Ubuntu-20.04

不出意外的话安装完成会提示创建一个新用户,这个用户是有root权限的,可以使用sudo -i来执行关键操作。

至此Linux子系统安装完成。

使用 VMware 部署

安装 VMware,完成后创建虚拟机。然后加载系统镜像,安装系统。

ubuntu中文官网

需要注意的是,安装时候会要求选择镜像地址,改成阿里云的 Ubuntu 镜像地址

http://mirrors.aliyun.com/ubuntu

当安装完成后会有提示:

finish: cmd-install: SUCCESS: curtin command install

之后就可以重启了。

使用 docker 部署

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

简单说 docker 是一个可以非常快速方便的在其中部署需要的环境的工具。有部署快速,性能接近于原生系统,多容器支持,易用易学习,极高的安全性等特点。

docker 的安装部署及使用可以参考

菜鸟教程

至于 docker 能帮我们做什么?最简单的就是环境的搭建,例如 redis 等各种服务都需要进行配置才能运行,而 docker 能够很简单的近乎免配置的搭建完成,甚至能分享并同步这些服务里的数据到需要的私有团队(仓库)中。

docker 原理

Docker 包括三个基本概念:

  • 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
  • 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
  • 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。

Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。

Docker 容器通过 Docker 镜像来创建。

概念 说明
Docker 镜像(Images) Docker 镜像是用于创建 Docker 容器的模板,比如 Ubuntu 系统。
Docker 容器(Container) 容器是独立运行的一个或一组应用,是镜像运行时的实体。
Docker 客户端(Client) Docker 客户端通过命令行或者其他工具使用 Docker SDK (https://docs.docker.com/develop/sdk/) 与 Docker 的守护进程通信。
Docker 主机(Host) 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。
Docker Registry Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。Docker Hub(https://hub.docker.com) 提供了庞大的镜像集合供使用。一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。

docker 从某种程度上讲是一个轻量化的虚拟机,但是和其他VM虚拟机还是有本质不同的:VM虚拟机(例如VMware)会重新加载一个操作系统,而docker是基于其宿主的操作系统来虚拟需要的环境。

docker 主要由服务端和客户端两部分组成,客户端向服务端发送命令,服务端来执行。

客户端建立仓库,保存镜像,在需要时向服务端发送指令,服务端启动镜像,生成容器。

安装 docker

docker 不是操作系统,本身也是需要基于操作系统启动的。所以这里分为 linux 下安装和 windows 下安装

使用 linux 系统

参考:Ubuntu18.04安装Docker

使用包管理工具

在 linux 上可以使用包管理器来装 docker

apt install docker.io

启动并添加为开机启动

systemctl start docker
systemctl enable docker

查看是否安装成功

docker -v

使用 docker 仓库

使用包管理工具可能安装的是旧版的 docker ,如果需要使用新版的,则可以从 docker 仓库安装

docker官方文档安装部分

首先卸载旧docker

apt remove docker docker-engine docker.io containerd runc

首先刷新并使用 HTTPS 方式从仓库里安装必要的证书

apt update
apt install apt-transport-https ca-certificates curl gnupg lsb-release

然后添加 docker 官方的 GPG 密钥

mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

添加 docker 官方仓库

echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

更新索引包并安装 docker 组件

apt update
apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin

如果执行 apt update 时收到一个 GPG error ,可以执行这条命令

chmod a+r /etc/apt/keyrings/docker.gpg

查看是否安装成功

docker -v

使用源代码安装

首先,需要知道使用的 linux 的具体版本信息

lsb_release -a

然后,根据版本信息下来 docker 的 deb 包

docker 官方源码库

最后使用 dpkg 工具安装源码包即可

安装完成后换源

docker 默认使用国外的源,如果想换成国内的源,可以参考

docker 换源

更换完成后,记得重启 docker 服务,可以使用 docker info 查看相关信息

使用 windows 系统

参考:Windows10下安装Docker
参考:菜鸟教程 Docker Desktop 安装

windows 下使用 docker 需要开启 Hyper-V,如果是 windows 系统直接开启,如果使用 VMware 安装的 windows 系统,则需要在 VM 中开启虚拟化后再开 Hyper-V

开启 VMware 的虚拟化

在 VM 的虚拟机设置 CPU 选项中,勾选 虚拟化 Intel VT-x/EPT 或 AMD-V/RVI 即可。如果勾选后进入虚拟机提示 此平台不支持虚拟化的Intel VT-x/EPT ,则是在宿主机中虚拟化没有完全关闭。

  1. 确定宿主机(物理机) BIOS 中开启了 VT
  2. 任务管理器->性能->CPU页 中查看本机是否启用了虚拟化
  3. 检查宿主机是否开启了 Hyper-V 三项:Hyper-V、Windows沙盒、虚拟机平台。如果开启了需要取消
  4. 打开Windows安全中心>设备安全性>内核隔离>内存完整性,将其关闭
  5. 在 CMD 中输入 bcdedit /set hypervisorlaunchtype off
  6. 重启计算机

这样就能完全关闭本地计算机的虚拟化了,VMware 也就能开启虚拟机的虚拟化了。

开启 windows 的虚拟化

在要安装 docker 的 windows 系统中,程序>打开关闭windows功能>Hyper-V ,将其开启。安装后会自动重启

Docker Desktop on Windows

Docker windows版官方下载地址

下载完成后进行安装即可,安装完成后需要重启电脑。

需注意的是,安装时会选择是否使用 wsl2 代替 Hyper-V,推荐是使用,不过需要先安装 wsl2。

  1. 首先在控制面板内,选择「程序和功能」,然后选择「启用或关闭 Windows 功能」,勾选「适用于 Linux 的 Windows 子系统」,然后点击确定后,计算机会提示需要重启。
  2. 很多教程会写“重启后,在 Microsoft Store 获取 Ubuntu”即可,但是实际上由于微软产品惯例挖坑的习惯,这里安装后大概率是无法正常启动的。这里我们需要先去微软官网,下载「适用于 x64 计算机的 WSL2 Linux 内核更新包」。

安装 wsl 的步骤,可以在旧版本的手动安装步骤中下载最新的 Linux 内核更新包

  1. 安装完成后在 PowerShell 内将 WSL2 设定为默认版本。

wsl --set-default-version 2

  1. 安装和设置完 WSL2 后,再安装 Ubuntu,就可以正常运行了。

如果docker开启时报错,可能是 wsl 有问题,可以选择安装 wsl 或不使用 wsl (在设置中关闭 **Use the WSL 2 based engine)

如果 wsl 一直报错无法解决,可以重新安装 docker desktop,取消 Use WSL 2 instead of Hyper-V,不使用 wsl 应该就可以了。

Docker Desktop 的使用

安装完成后,启动 docker 服务,程序栏中会有鲸鱼图标出现。等待 Docker Starting 一段时间,直到提示已经启动就可以了。可以打开 PowerShell 并运行以下命令检测是否运行成功:

docker run hello-world
docker version

运行成功后就可以正常使用了

Docker Desktop 换源

默认 docker 使用的是国外的源。如果需要换源,docker desktop 可以在设置中,docker engine 里,设置新的源:
在这里插入图片描述

开启 docker 服务

查看 docker 是否开启

systemctl status docker

启动服务并添加为开机启动

systemctl start docker
systemctl enable docker

如果有需要,可以禁止 docker 自动更新

apt-mark hold docker-ce

docker 运行时自动运行容器

在一些情况下(重启服务器等)重启 docker 服务,可以使用 restart policies 自动运行需要的容器。在创建容器时添加参数 --restart=always 即可。

–restart 参数可用配置:

  • no - 容器退出时,不重启容器
  • on-failure - 只有在非0状态退出时才从新启动容器
  • always - 无论退出状态是如何,都重启容器

如果创建时未指定 --restart=always ,可通过update 命令设置

docker update --restart=always 容器名称  

还可以在使用on - failure策略时,指定Docker将尝试重新启动容器的最大次数。默认情况下,Docker将尝试永远重新启动容器。

docker run --restart=on-failure:10 redis

使用restart policies时需要注意如下细节:

  1. 容器只有在成功启动后restart policy才能生效。这里的"成功启动"是指容器处于up至少10秒且已经处于docker监管。这是避免没有成功启动的容器陷入restart的死循环。
  2. 如果手动(manually)的stop(与前面的explicitly stopped有何区别)一个容器,容器设置的restart policy将会被忽略,除非Docker daemon重启或者容器手动重启。这是避免了另外一种死循环。
  3. restart policies 只能用于容器,对于swarm services其restart policies有不通过的配置。

docker 的使用

docker 的使用流程是

  • 搜索镜像
  • 下载镜像
  • 启动镜像,创建容器
    至此部分简单的服务软件已经可以使用了,还有些较复杂的则需要继续
  • 进入容器

常用命令

  • docker version : 查看具体版本信息
  • docker search 镜像名 : 搜索具体镜像
  • docker pull 镜像具体名称 : 下载镜像
  • docker run 镜像具体名称 : 启动镜像
  • docker images : 查看所有本地镜像
  • docker ps : 查看容器状态,可以添加参数 -a 显示隐藏(未运行),-s 显示占用空间
  • docker system : 查看 docker 系统信息,需配合参数使用,例如 docker system df -v 能查看每一个镜像、容器占用空间。
  • docker system prune : 清除无用的资源,包括停止的容器、没使用的镜像、卷、网络等等

搜索镜像

搜索 redis 软件信息

docker search redis

或者可以从 docker 的官方网站搜索获取镜像信息和下载名称

docker 官方镜像仓库

下载镜像

根据搜索到的软件名称(版本)来下载镜像

docker pull redis

如果太慢可以换成国内镜像

docker拉取pull速度太慢解决办法(全)

不过目前目前由于Docker Hub限制,导致使用镜像加速器后无法获取最新官方镜像。请暂时去掉加速器配置,直接连接Docker Hub获取。

本地镜像管理

对于下载到本地的镜像,可以进行管理

  • docker images : 列出本地镜像
  • docker rmi : 删除本地一个或多个镜像
  • docker tag : 更改镜像名称
  • docker inspect : 获取容器/镜像的元数据
  • docker history : 获取镜像历史信息

对于本地镜像,可以保存至本地文件,也可以从本地文件导入到镜像

  • docker save : 保存镜像为本地文件,使用参数 -o 确定保存本地文件名
  • docker export : 导出镜像到本地文件
  • docker import : 导入本地文件至镜像(只能导入 .tar.gz 类型)
  • docker load : 将保存为本地文件的镜像,再次装载至本地镜像(例如误删除)
    load 类似于 import 区别在于 load 会导入分层和历史信息,所以导入的数据大一些。save 和 export 的区别相同。

启动镜像,创建容器

使用 run 或 create 命令来运行下载好的镜像,参数组合中 d 是后台运行容器并返回容器ID,i 是交互式操作,t 是使用终端;附带参数 --name 后为容器名称(一个镜像能运行多次),然后 -p 是要附带ip(如没有ip参数则默认0.0.0.0)和端口的映射(格式为:主机(宿主)端口:容器端口),最后是要运行的镜像服务。

这样就能够创建一个此镜像生成的容器,容器名称就是 --name 指定名称。run 和 create 的区别在于,create 创建一个新的容器但不启动它

docker run -dit --name redis1 -p 6300:6379  redis

还有一些有用的参数可能会被用到:

  • -e : 设置环境变量,例如 `-e MYSQL_ROOT_PASSWORD=root_mysql
  • -P : 随机端口映射,容器内部端口随机映射到主机的端口,和 -p 互斥
  • -h : 指定容器的hostname

另外可以查看正在运行容器信息

docker ps

还可以使用参数:-a 显示所有的容器(包括未运行的)、-l 显示最近创建的容器、-n 列出最近创建的n个容器

对容器生命周期的操作

对于已经建立的容器,可以执行以下操作:

  • docker start : 启动一个或多个已经被停止的容器
  • docker stop : 停止一个运行中的容器,支持“优雅退出”。先发送SIGTERM信号,在一段时间之后(10s)再发送SIGKILL信号。Docker内部的应用程序可以接收SIGTERM信号,然后做一些“退出前工作”,比如保存状态、处理当前请求等
  • docker kill : 杀掉一个运行中的容器,发送SIGKILL信号,应用程序直接退出
  • docker restart : 重启容器
  • docker rm : 删除一个或多个容器,可以使用参数 -f 删除运行中的容器、-l 移除容器间的网络连接而非容器本身、-v 删除与容器关联的卷;另外可以使用 docker rm $(docker ps -a -q) 删除所有已经停止的容器
  • docker pause : 暂停容器中所有的进程。
  • docker unpause : 恢复容器中所有的进程
  • docker rename : 容器更该名称

对容器内容信息的操作

对正在运行的容器,可以执行以下操作来查看一些信息

  • docker logs : 获取容器的日志
    可用的参数有 -f 跟踪日志输出、-t 显示时间戳、–tail 仅列出最新N条容器日志、–since 显示某个开始时间的所有日志
  • docker top : 查看容器中运行的进程信息,支持 ps 命令参数。
  • docker inspect : 获取容器/镜像的元数据

容器互联

docker 中的容器是隔离的,如果想访问则需要通过端口映射到宿主端口,这样互相访问有些麻烦。端口映射并不是唯一把 docker 连接到另一个容器的方法,有一个连接系统允许将多个容器连接在一起,共享连接信息。

先创建一个新的 docker 网络,-d bridge 指定网络类型为桥接,最后的 test-net 是网络连接名称。

docker network create -d bridge test-net

然后可以将两个容器添加到网络中,在创建容器的时候指定网络到新建立的连接中

docker run -itd --name test1 --network test-net redis /bin/bash
docker run -itd --name test2 --network test-net redis /bin/bash

这样两个容器就可以互相访问了,可以在容器内部使用 ping 进行网络测试,如果容器本身没有 ping 工具可以现安装

apt-get update
apt install iputils-ping
docker exec -it test1 /bin/bash
ping test2
docker exec -it test2 /bin/bash
ping test1

docker 网络的一些其他操作

  • docker network connect : 连接一个容器到网络
  • docker network disconnect : 断开一个容器网络的连接
  • docker network ls : 列出所有网络
  • docker network prune : 删除所有没有使用的网络
  • docker network rm : 删除一个或多个网络

进入容器

可以使用 docker exec 在运行的容器中执行命令

docker exec redis1 ls

这个命令的意思是在 redis1 容器内执行 ls 指令(因为容器是基于现有宿主环境建立的,即使用的 linux 系统)。也可以使用一个伪终端进入容器进行操作

docker exec -it redis1 /bin/bash

容器和宿主机的文件交换

可以使用命令 docker cp 将 docker 的文件复制到宿主机本地,也可以反向操作。格式为

docker cp 容器:容器内文件路径 本地文件路径
docker cp 本地文件路径 容器:容器内文件路径

对于已经运行的容器的端口映射

docker 在创建容器时可以设置端口映射,但是如果已经运行的容器,需要增加映射的端口有3种方法:

  1. 将容器打包成镜像,然后再次运行此镜像。
    这种方法很简单,但是如果容器比较大,打包就不太方便了。
  2. 使用 iptable 转发端口,例如将容器的8000端口映射到docker主机的8001端口
iptables -t nat -A  DOCKER -p tcp --dport 8001 -j DNAT --to-destination 172.17.0.19:8000
  1. 修改 docker 的配置文件:/var/lib/docker/containers/[hash_of_the_container]/hostconfig.jsonconfig.v2.json
    [hash_of_the_container] 是仓库的 hash 码,即仓库的 id,可以使用 docker inspect 容器名称 来查看。注意修改时需要先将 docker 的服务停止。hostconfig.json 里有 "PortBindings":{} 可以改成 "PortBindings":{"80/tcp":[{"HostIp":"","HostPort":"8080"}]},这里80是容器端口,8080是本地端口。然后在 config.v2.json 里添加一个配置项 "ExposedPorts":{"80/tcp":{}},,将这个配置项添加到 "Try": true,(如果是false则改为true) 前面,就是将此80端口暴漏出来。然后重启 docker 的守护进行即可 service docker restart。这里有个问题是重启后,使用 docker ps -a 是看不到端口映射的,但是通过 docker inspect 容器名 可以看到配置项已经修改成功,且能够使用了。

创建镜像

当现有的镜像不能满足我们的需求,或者想打包自己的环境,可以通过更新镜像或自己从零开始创建一个镜像。

更新镜像

当创建好了容器后,在容器内部有了改动,例如在运行的容器内使用 apt-get update 命令进行更新。然后可以提交容器副本成为新的镜像

docker commit -m "has update" -a "user_li" e218edb10161 root/redis:v2
  • -m : 提交的描述信息
  • -a: 指定镜像作者
  • e218edb10161:容器 ID
  • root/redis:v2 : 指定要创建的目标镜像名及 tag

提交后可以使用 docker images 命令来查看新镜像,也可以使用这个新镜像来构建容器。

创建新镜像

创建新镜像主要分为建立 Dockerfile 和使用 Dockerfile 构建镜像两部分。

创建 Dockerfile

创建一个用来构建镜像的文本文件 Dockerfile ,其文本内容包含了一条条构建镜像所需的指令和说明。

root@linux:~$ cat Dockerfile 
FROM    centos:6.7
MAINTAINER      Fisher "[email protected]"
RUN     /bin/echo 'root:123456' |chpasswd
RUN     useradd user_li
RUN     /bin/echo 'user_li:123456' |chpasswd
RUN     /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local
EXPOSE  22
EXPOSE  80
CMD     /usr/sbin/sshd -D

每一个指令都会在镜像上创建一个新的层,每一个指令的前缀都必须是大写的。

FROM:定制的镜像都是基于 FROM 的镜像,如果不以任何镜像为基础,那么写法为:FROM scratch
MAINTAINER : 声明作者信息
RUN:用于执行后面跟着的命令行命令。可以执行 shell (命令行命令,等同于在终端操作的 shell 命令) 和 exec (执行可执行文件,可以附带参数)

需注意的是,Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

FROM centos
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN gunzip redis.tar.gz
RUN tar -xvf redis.tar

以上执行会创建 3 层镜像。可以使用 && 符号连接命令,这样执行后,只会创建 1 层镜像。

FROM centos
RUN yum -y install wget \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && gunzip redis.tar.gz \
    && tar -xvf redis.tar

举例一个开发环境实例:

FROM ubuntu-dev:latest
MAINTAINER disen [email protected]
WORKDIR /usr/src
RUN	apt update \
	&& apt install cron
RUN git clone https://github.com/dabaicai233/v2ex.git
RUN pip3 install scrapy -i https://mirrors.aliyun.com/pypi/simple
WORKDIR /usr/scr/v2ex/v2ex
RUN chmod +x start_spider.sh
RUN crontab crontab.cron
CMD python3

构建镜像

在 Dockerfile 文件的存放目录下,使用 docker build 执行构建动作。

docker build -t redis:v3 .
  • -t :指定要创建的目标镜像名
  • . : Dockerfile 文件所在路径,可以是绝对路径
    由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。

Dockerfile 指令详解

Dockerfile详解超全

Dockerfile 文件除了 FROM 和 RUN 外,还可以使用这些指令:

COPY

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

格式:

COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",...  "<目标路径>"]

[–chown=:]:可选参数,用户改变复制到容器内文件的拥有者和属组。
<源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:

COPY hom* /mydir/
COPY hom?.txt /mydir/

<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

ADD

ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
CMD

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

  • CMD 在docker run 时运行。
  • RUN 是在 docker build。
    作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
    注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
    格式:
CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...] 
CMD ["<param1>","<param2>",...]  # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。

ENTRYPOINT

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。
但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。
优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
格式:

ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参。例如:
假设已通过 Dockerfile 构建了 nginx:test 镜像:

FROM nginx

ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参 

1、不传参运行

$ docker run  nginx:test

容器内会默认运行以下命令,启动主进程。

nginx -c /etc/nginx/nginx.conf

2、传参运行

$ docker run  nginx:test -c /etc/nginx/new.conf

容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)

nginx -c /etc/nginx/new.conf
ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。格式:

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
ARG

构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。
构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。
格式:

ARG <参数名>[=<默认值>]
VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。作用:

  • 避免重要的数据,因容器重启而丢失,这是非常致命的。
  • 避免容器不断变大。

格式:

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

仅仅只是声明端口。作用:

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
  • 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
    格式:
EXPOSE <端口1> [<端口2>...]
WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

WORKDIR <工作目录路径>
USER

用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。

USER <用户名>[:<用户组>]
HEALTHCHECK

用于指定某个程序或者指令来监控 docker 容器服务的运行状态。

HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。
ONBUILD

用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。

ONBUILD <其它指令>
LABEL

LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:

LABEL <key>=<value> <key>=<value> <key>=<value> ...

比如我们可以添加镜像的作者:

LABEL org.opencontainers.image.authors="lilei"

python 的库支持

在部署生产环境时,需要先安装支持库。通常是根据 requirements.txt 来安装依赖库。

生成 requirements.txt

通常有两种方式:Python里的 freeze 和第三方库 pipreqs

freeze 方法

在终端项目目录下执行命令,就能够直接生成。

pip freeze > requirements.txt

这种方法简单但是并不推荐使用。
如果在写的项目是使用虚拟环境写的,就可以使用这个方法,因为这个方法会将你整个Python环境的包全把生成出来。
如果你不是使用虚拟环境,使用这个方法,你会发现生成的文件,里面有很多你并不需要的包,这样使用安装的依赖包的时候会有很多不需要的包。

pipreqs

pipreqs 是个第三方库,使用 pipreqs 可以自动检索到当前项目下的所有组件及其版本,并生成 requirements.txt 文件,极大方便了项目迁移和部署的包管理。相比直接用pip freeze 命令,能直接隔离其它项目的包生成。

使用时需要先安装库

pip install pipreqs

然后在项目目录中执行

pipreqs ./ --encoding=utf8 --force

–encoding=utf8 :使用utf8编码
–force :强制执行,当生成目录下的requirements.txt存在时覆盖
. /: 生成requirements.txt 文件的路径

安装依赖库

可以根据 requirements.txt 来安装需要使用的依赖库

pip install -r requirements.txt

猜你喜欢

转载自blog.csdn.net/runsong911/article/details/126994111