个人理解:容器是镜像的实例化,如把镜像比作Python中的类,则容器即为类的实例。想要给类中的方法传递参数,则有三种方法:
1. 在编写类的代码时直接将参数写在类文件中,然后方法使用对应的参数。这种方式对应直接在Dockerfile中将参数写在ENTRYPOINT或CMD里。
2. 类具有构造方法(对应到Python中的类即表示类具有__init__方法)时,在创建类的实例的时候传递参数,然后类中的方法使用对应的参数开始执行。这种方式对应下述第1节“启动镜像生成容器时传递参数”介绍的方法。
3. 给正在运行的类的实例传递参数,此时类已被实例化,该实例正在运行,如Python中通过__setattr__这种方式给实例设置参数(属性及属性值),然后类中的方法使用对应的参数开始执行。这种方式对应下述第2节“给正在运行的容器传递参数”介绍的方法。
1. 启动镜像生成容器时传递参数
下面记录使用Docker封装Python项目为镜像,然后在启动镜像时传递参数的用法。
Docker项目结构:
dockerTestFolder
----Dockerfile
----PythonProjectFolder
--------test.py
--------requirements.txt
其中test.py接收两个参数“name”和“year”,其内容如下:
import click
@click.command()
@click.option('--name',default='Python',help='default=Python')
@click.option('--year',help='default=none',type=int)
def myprint(year, name):
print('the year is', year)
print('the name is', name)
if __name__ == '__main__':
myprint()
requirements.txt的生成方式为:
在dockerTestFolder目录下,运行“pipreqs PythonProjectFolder”,此命令需要使用pip安装pipreqs:“pip3 install pipreqs”。
编写Dockerfile的内容:
FROM python:3.6.8
MAINTAINER name youremail
COPY ./PythonProjectFolder /code
workdir /code
run pip install -r requirements.txt
cmd ["python", "test.py"]
在dockerTestFolder目录下创建Docker镜像(注意最后面有一个点,代表当前目录):
docker build -t docker_pass_params_test_img .
若出现以下异常:
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x7f3bd7ef7208>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution',)': /simple/click/
WARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x7f3bd7ef74e0>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution',)': /simple/click/
WARNING: Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x7f3bd7ef75c0>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution',)': /simple/click/
WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x7f3bd7ef77f0>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution',)': /simple/click/
WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x7f3bd7ef7908>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution',)': /simple/click/
ERROR: Could not find a version that satisfies the requirement click==8.0.3 (from -r requirements.txt (line 1)) (from versions: none)
ERROR: No matching distribution found for click==8.0.3 (from -r requirements.txt (line 1))
则执行:
docker build --network=host -t docker_pass_params_test_img .
得到镜像 docker_pass_params_test_img,镜像生成容器时不传递参数,直接运行镜像:
docker run docker_pass_params_test_img
输出:
the year is None
the name is Python
镜像生成容器时传递参数,运行镜像:
docker run docker_pass_params_test_img python3 test.py --year 2021
输出:
the year is 2021
the name is Python
其中参数为[python3, test.py, --year 2021],前两个参数直接覆盖掉Dockerfile中CMD所指定的参数,最后一个参数为传给python函数的参数。
2. 给正在运行的容器传递参数
Docker项目结构和Python项目结构同上。Python文件、Dockerfile和requirements.txt的内容或生成方式也同上。
不同点:由于给容器传递参数时需要容器在运行状态,所以在使用镜像生成容器时,需要生成一个能够保持长时间运行且能交互的容器,指令如下:
docker run -it -d --name pass_params_test_container docker_pass_params_test_img /bin/bash
其中 docker_pass_params_test_img 即为1中创建的镜像,pass_params_test_container为生成的容器的名字,使用/bin/bash来支持该容器能够进行交互和后台运行(也可以使用其他的方法,不过该方法简单方便)。此时会生成名为“pass_params_test_container”的容器,以具有交互功能的方式启动容器:
docker start -i pass_params_test_container
然后在另一个终端下给正在运行的容器pass_params_test_container传递参数并执行:
docker exec -it pass_params_test_container python3 test.py --year 2021
输出:
the year is 2021
the name is Python
上述介绍了如何给镜像/容器传递参数的两种方法,若有错误之处欢迎指正。