cee*_*pie 8 windows powershell docker dockerfile docker-compose
project\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80app\n\xe2\x94\x82 \xe2\x94\x82 ...\n\xe2\x94\x82 \xe2\x94\x82 Dockerfile\n\xe2\x94\x82 \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80prod.env\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80docker-compose.yml\n
Run Code Online (Sandbox Code Playgroud)\n我的 docker-compose 看起来像这样:
\nservices:\n app:\n build:\n context: .\\app\n args:\n ARG1: val1\n ARG2: val2\n env_file:\n - prod.env\n
Run Code Online (Sandbox Code Playgroud)\n但我也尝试过这个:
\nservices:\n app:\n build:\n context: .\\app\n args:\n ARG1: ${ARG1}\n ARG2: ${ARG2}\n env_file:\n - prod.env\n
Run Code Online (Sandbox Code Playgroud)\n我的 prod.env 文件如下所示:
\nARG1 = 'val1'\nARG2 = 'val2'\n
Run Code Online (Sandbox Code Playgroud)\n但我也尝试过这个:
\nARG1=val1\nARG2=val2\n
Run Code Online (Sandbox Code Playgroud)\n我希望将 args 的值或 prod.env 文件中的值传递给 dockerfile。
\n这就是我试图得到的:
\nARG ARG1\nARG ARG2\n\nRUN echo ${ARG1}\nRUN echo ${ARG2}\n
Run Code Online (Sandbox Code Playgroud)\nENV ARG1 ${ARG1}\nENV ARG2 ${ARG2}\n\nRUN echo ${ARG1}\nRUN echo ${ARG2}\n
Run Code Online (Sandbox Code Playgroud)\nENV ARG1 "new val2"\nENV ARG2 "new val2"\n\nRUN echo ${ARG1}\nRUN echo ${ARG2}\n
Run Code Online (Sandbox Code Playgroud)\n它总是以空白值结尾。
\n任何帮助将不胜感激。当我尝试时,我觉得其他帖子的答案都不起作用。
\n为了构建我使用docker-compose --env-file prod.env build
谢谢
\n更新\nSergio Santiago 询问我是否可以运行docker-compose config
并显示结果。
这是我用于此测试的最终文件。
\ndocker-撰写:
\nservices:\n app:\n build:\n context: .\\app\n args:\n ARG1: val1\n ARG2: val2\n env_file:\n - prod.env\n
Run Code Online (Sandbox Code Playgroud)\n产品环境:
\nARG3 = 'val3'\nARG4 = 'val4'\n
Run Code Online (Sandbox Code Playgroud)\n这是输出docker-compose --env-file prod.env config
networks:\n demo-net: {}\nservices:\n app:\n build:\n args:\n ARG1: val1\n ARG2: val2\n context: C:\\project\\app\n environment:\n ENV: prod.env\n ARG3: val3\n ARG4: val4\n
Run Code Online (Sandbox Code Playgroud)\n我想补充一点,从这里显然将变量从 .env 文件获取到 docker-compose 文件不是问题。我还有一个在容器上运行的 Flask 应用程序,通过 os.environ 它可以使用 .env 文件中的变量。我只是不知道如何授予对 Dockerfile 的相同访问权限。
\n更新 2 \n与 ErikMD 的答案相关的更多具体信息
\n产品环境
\nDOMAIN = 'actualdomain.com'\nENV = 'prod.env'\nENV_NUM = 1\nARG1 = 'value1'\n
Run Code Online (Sandbox Code Playgroud)\n开发环境
\nDOMAIN = 'localhost'\nENV = 'dev.env'\nENV_NUM = 0\nARG1 = 'value1'\n
Run Code Online (Sandbox Code Playgroud)\n请注意,ARG1 的值相同,但其他值不同。
\ndocker-compose.yml
\nversion: "3.7"\nservices:\n home:\n image: home-${ENV_NUM}\n build: \n context: .\\home\n args:\n ARG1: "${ARG1}"\n networks:\n - demo-net\n env_file:\n - ${ENV}\n labels:\n - traefik.enable=true\n - traefik.http.routers.home.rule=Host(`${DOMAIN}`)\n - traefik.http.routers.home.entrypoints=web\n volumes:\n - g:\\:c:\\sharedrive\n...\n...\n reverse-proxy:\n restart: always\n image: traefik:v2.6.1-windowsservercore-1809\n command:\n - --api.insecure=true\n - --providers.docker=true\n - --entrypoints.web.address=:80\n - --providers.docker.endpoint=npipe:////./pipe/docker_engine\n ports:\n - 80:80\n - 443:443\n - 8080:8080\n networks:\n - demo-net\n volumes:\n - source: \\\\.\\pipe\\docker_engine\\\n target: \\\\.\\pipe\\docker_engine\\\n type: npipe\nnetworks:\n demo-net:\n
Run Code Online (Sandbox Code Playgroud)\n这些点代表其他应用程序的格式与主页相同。
\ndocker文件
\nFROM python:3.10.3\n\nARG ARG1="default"\n\nENV ARG1="${ARG1}"\n\nWORKDIR /app\n\nENV PYTHONDONTWRITEBYTECODE 1\nENV PYTHONUNBUFFERED 1\n\nRUN echo "This is argument 1 -> ${ARG1}"\n
Run Code Online (Sandbox Code Playgroud)\n的输出docker-compose --env-file prod.env config
networks:\n demo-net: {}\nservices:\n home:\n build:\n args:\n ARG1: value1\n context: C:\\MIS-Web-App\\home\n environment:\n DOMAIN: actualdomain.com\n ENV: prod.env\n ENV_NUM: '1'\n ARG1: value1\n image: home-1\n labels:\n traefik.enable: "true"\n traefik.http.routers.home.entrypoints: web\n traefik.http.routers.home.rule: Host(`mis.canaras.net`)\n networks:\n demo-net: null\n volumes:\n - g:\\:c:\\sharedrive:rw\n...\n...\n
Run Code Online (Sandbox Code Playgroud)\n然后我运行docker-compose --env-file prod.env build
或者docker-compose --env-file dev.env build
构建的输出
\nStep 9/23 : RUN echo "This is argument 1 -> ${ARG1}"\n ---> Running in 5142850de365\nThis\nis\nargument\n1\n->\nRemoving intermediate container 5142850de365\n
Run Code Online (Sandbox Code Playgroud)\n现在我在命令和实际文件中调用传递 env_file ,因为其中有我的 docker-compose 文件需要的变量和我的 Flask 应用程序需要的变量。并且肯定存在重叠。
\n将 prod.env 或 dev.env 文件中的值获取到 docker-compose 不是问题。也没有将它添加到我的烧瓶应用程序中。问题是将这些值获取到 dockerfile。
\n我正在发布一个新答案,以强调与OP问题相关的各种假设,特别是".env"
唯一文件名和*.env
文件( 的参数env_file:
)之间存在细微差别的事实。
docker-compose.yml
但除了这种微妙之处之外,从到docker build -f Dockerfile .
和/或传递参数的过程docker run -e \xe2\x80\xa6
很简单,如下面的综合示例所示。
让我们考虑给定目录中的以下文件,例如./docker
.
文件docker-compose.yml
:
services:\n demo-1:\n image: demo-${ENV_NUM}\n build:\n context: .\n args:\n ARG1: "demo-1/${ARG1}"\n ARG3: "demo-1/${ARG3}"\n demo-2:\n image: demo-2${ENV_FILE_NUM}\n build:\n context: .\n args:\n ARG1: "demo-2/${ARG1}"\n ARG3: "demo-2/${ARG3}"\n env_file:\n - var.env\n
Run Code Online (Sandbox Code Playgroud)\n备注:即使我们使用字段,也添加一个字段来自动标记构建的图像build:
似乎是一个好主意;image:
但请注意,这些图像名称必须成对不同。
文件.env
:
KEY="some value"\nENV_NUM=1\nARG1=.env/ARG1\nARG2=.env/ARG2\nARG3=.env/ARG3\n
Run Code Online (Sandbox Code Playgroud)\n文件var.env
:
ENV_FILE_NUM="some number"\nARG1=var.env/ARG1\nARG2=var.env/ARG2\nARG3=var.env/ARG3\nARG4=var.env/ARG4\n
Run Code Online (Sandbox Code Playgroud)\n文件Dockerfile
:
FROM debian:10\n\n# Read build arguments (default value if omitted at CLI)\nARG ARG1="default 1"\nARG ARG2="default 2"\nARG ARG3="default 3"\n\n# the build args are exported at build time\nRUN echo "ARG1=${ARG1}" | tee /root/arg1.txt\nRUN echo "ARG2=${ARG2}" | tee /root/arg2.txt\nRUN echo "ARG3=${ARG3}" | tee /root/arg3.txt\n\n# Export part of these args at runtime also\nENV ARG1="${ARG1}"\nENV ARG2="${ARG2}"\n\n# exec-form is mandatory for ENTRYPOINT/CMD\nCMD ["/bin/bash", "-c", "echo ARG1=\\"${ARG1}\\" ARG2=\\"${ARG2}\\" ARG3=\\"${ARG3}\\"; echo while at build time:; cat /root/arg{1,2,3}.txt"]\n
Run Code Online (Sandbox Code Playgroud)\n首先,正如 @SergioSantiago 在评论中所建议的docker-compose.yml
,在插值后预览有效文件的一个非常方便的命令是docker-compose config
:
$ docker-compose config\n\nWARN[0000] The "ENV_FILE_NUM" variable is not set. Defaulting to a blank string. \nname: docker\nservices:\n demo-1:\n build:\n context: /home/debian/docker\n dockerfile: Dockerfile\n args:\n ARG1: demo-1/.env/ARG1\n ARG3: demo-1/.env/ARG3\n image: demo-1\n networks:\n default: null\n demo-2:\n build:\n context: /home/debian/docker\n dockerfile: Dockerfile\n args:\n ARG1: demo-2/.env/ARG1\n ARG3: demo-2/.env/ARG3\n environment:\n ARG1: var.env/ARG1\n ARG2: var.env/ARG2\n ARG3: var.env/ARG3\n ARG4: var.env/ARG4\n ENV_FILE_NUM: some number\n image: demo-2\n networks:\n default: null\nnetworks:\n default:\n name: docker_default\n
Run Code Online (Sandbox Code Playgroud)\n在这里,正如警告所示,我们看到插值存在问题ENV_FILE_NUM
,尽管 提到了这个变量var.env
。原因是env_file
s行只是为底层docker run -e \xe2\x80\xa6
命令添加新的环境变量,但不会在docker-compose.yml
.
ARG1=.env/ARG1
相反,我们可以注意到,从 中获取的值".env"
是在args:
的字段内插值的docker-compose.yml
,参见 1。输出线:
args:\n ARG1: demo-1/.env/ARG1\n \xe2\x80\xa6\n
Run Code Online (Sandbox Code Playgroud)\n".env"
与s的这种非常不同的语义在官方文档的本页env_file
中进行了描述。
接下来,让我们运行:
\n$ docker-compose up --build\n \nWARN[0000] The "ENV_FILE_NUM" variable is not set. Defaulting to a blank string. \n[+] Building 10.4s (13/13) FINISHED\n => [demo-1 internal] load build definition from Dockerfile\n => => transferring dockerfile: 609B\n => [demo-2 internal] load build definition from Dockerfile\n => => transferring dockerfile: 609B\n => [demo-1 internal] load .dockerignore\n => => transferring context: 2B\n => [demo-2 internal] load .dockerignore\n => => transferring context: 2B\n => [demo-2 internal] load metadata for docker.io/library/debian:10\n => [demo-2 1/4] FROM docker.io/library/debian:10@sha256:ebe4b9831fb22dfa778de4ffcb8ea0ad69b5d782d4e86cab14cc1fded5d8e761\n => => resolve docker.io/library/debian:10@sha256:ebe4b9831fb22dfa778de4ffcb8ea0ad69b5d782d4e86cab14cc1fded5d8e761\n => => sha256:85bed84afb9a834cf090b55d2e584abd55b4792d93b750db896f486680638344 50.44MB / 50.44MB\n => => sha256:ebe4b9831fb22dfa778de4ffcb8ea0ad69b5d782d4e86cab14cc1fded5d8e761 1.85kB / 1.85kB\n => => sha256:40dd1c1b1c36eac161ab63b6ce3a57d56ad79a667a37717a31721bac3f30aaf9 529B / 529B\n => => sha256:26a2b081e03207d26a105340161109ba0f00e857cbb0ff85aaeeeadd46b709c5 1.46kB / 1.46kB\n => => extracting sha256:85bed84afb9a834cf090b55d2e584abd55b4792d93b750db896f486680638344\n => [demo-2 2/4] RUN echo "ARG1=demo-2/.env/ARG1" | tee /root/arg1.txt\n => [demo-1 2/4] RUN echo "ARG1=demo-1/.env/ARG1" | tee /root/arg1.txt\n => [demo-1 3/4] RUN echo "ARG2=default 2" | tee /root/arg2.txt\n => [demo-2 3/4] RUN echo "ARG2=default 2" | tee /root/arg2.txt\n => [demo-2 4/4] RUN echo "ARG3=demo-2/.env/ARG3" | tee /root/arg3.txt\n => [demo-1 4/4] RUN echo "ARG3=demo-1/.env/ARG3" | tee /root/arg3.txt\n => [demo-2] exporting to image\n => => exporting layers\n => => writing image sha256:553f294a410ceeb3c0ac9d252d443710c804d3f7437ad7fffa586967517f5e7a\n => => naming to docker.io/library/demo-1\n => => writing image sha256:84bb2bd0ffae67ffed0e74efbf9253b6d634a6f37c6f99bc4eedea81846a9352\n => => naming to docker.io/library/demo-2\n \nUse \'docker scan\' to run Snyk tests against images to find vulnerabilities and learn how to fix them\n[+] Running 3/3 \n \xe2\xa0\xbf Network docker_default Created\n \xe2\xa0\xbf Container docker-demo-1-1 Created\n \xe2\xa0\xbf Container docker-demo-2-1 Created\n
Run Code Online (Sandbox Code Playgroud)\nAttaching to docker-demo-1-1, docker-demo-2-1\n\ndocker-demo-1-1 | ARG1=demo-1/.env/ARG1 ARG2=default 2 ARG3=\ndocker-demo-1-1 | while at build time:\ndocker-demo-1-1 | ARG1=demo-1/.env/ARG1\ndocker-demo-1-1 | ARG2=default 2\ndocker-demo-1-1 | ARG3=demo-1/.env/ARG3\n\ndocker-demo-2-1 | ARG1=var.env/ARG1 ARG2=var.env/ARG2 ARG3=var.env/ARG3\ndocker-demo-2-1 | while at build time:\ndocker-demo-2-1 | ARG1=demo-2/.env/ARG1\ndocker-demo-2-1 | ARG2=default 2\ndocker-demo-2-1 | ARG3=demo-2/.env/ARG3\n\ndocker-demo-1-1 exited with code 0\ndocker-demo-2-1 exited with code 0\n
Run Code Online (Sandbox Code Playgroud)\n在这里,我们再次看到,".env"
价值观和价值观file_env: [ filename.env ]
扮演着不同的角色,并不重叠。
此外:
\nENV ARG3="${ARG3}"
,因此 build-arg 的值ARG3
不会在运行时传播(请参阅ARG3=
上面输出中的行)。environment:
但是,如果在文件中的或env_file:
部分中定义/覆盖了该值,则无论如何都可以在运行时导出该值docker-compose.yml
(请参阅ARG3=var.env/ARG3
上面输出中的行)。有关更多详细信息,请参阅该ARG
指令的文档。
docker-compose --env-file
选项用例的备注正如OP所提到的,docker-compose
还享有一个有用的CLI选项--env-file
(它的命名方式与非常不同的字段完全相同env-file:
,这是不幸的,但没关系)。
此选项允许以下用例(摘自 OP 的代码):
\n文件docker-compose.yml
:
Attaching to docker-demo-1-1, docker-demo-2-1\n\ndocker-demo-1-1 | ARG1=demo-1/.env/ARG1 ARG2=default 2 ARG3=\ndocker-demo-1-1 | while at build time:\ndocker-demo-1-1 | ARG1=demo-1/.env/ARG1\ndocker-demo-1-1 | ARG2=default 2\ndocker-demo-1-1 | ARG3=demo-1/.env/ARG3\n\ndocker-demo-2-1 | ARG1=var.env/ARG1 ARG2=var.env/ARG2 ARG3=var.env/ARG3\ndocker-demo-2-1 | while at build time:\ndocker-demo-2-1 | ARG1=demo-2/.env/ARG1\ndocker-demo-2-1 | ARG2=default 2\ndocker-demo-2-1 | ARG3=demo-2/.env/ARG3\n\ndocker-demo-1-1 exited with code 0\ndocker-demo-2-1 exited with code 0\n
Run Code Online (Sandbox Code Playgroud)\n文件prod.env
:
services:\n home:\n image: home-${ENV_NUM}\n build:\n args:\n ARG1: "${ARG1}"\n ...\n labels:\n - traefik.http.routers.home.rule=Host(`${DOMAIN}`)\n ...\n env_file:\n - ${ENV}\n
Run Code Online (Sandbox Code Playgroud)\n文件dev.env
:
DOMAIN = \'actualdomain.com\'\nENV = \'prod.env\'\nENV_NUM = 1\nARG1 = \'value 1\'\n
Run Code Online (Sandbox Code Playgroud)\n然后运行:
\ndocker-compose --env-file prod.env build
,docker-compose --env-file dev.env build
顺便说一句,即使到目前为止这个答案的大部分内容都说明了".env"
文件名和env_file:
文件具有非常不同的语义\xe2\x80\xa6,但确实它们也可以按照建议的方式“很好地”组合由OP来实现这个用例。
顺便请注意,这docker-compose config
也适用于“调试”Compose 规范:
docker-compose --env-file prod.env config
,docker-compose --env-file dev.env config
。现在关于最后一个问题:
\n\n\n\n
prod.env
从或dev.env
文件获取值docker-compose
不是问题。问题是将这些值传递到Dockerfile
.
首先可以注意到有两种不同的情况:
\nprod.env
和dev.env
)可以共享相同的映像,因此差异仅在于运行时环境变量(而不是docker build args)。--env-file
,图像应该不同(然后 adocker-compose --env-file \xe2\x80\xa6 build
确实是必要的)。看来大多数时候,情况 1. 是可以实现的(问题的配置也是如此,因为和ARG1
中的值相同)并且可以被视为更有趣可重复性(因为我们确信“prod”图像与“dev”图像相同)。prod.env
dev.env
然而,有时这是不可能的,我们处于“情况 2”,例如,如果Dockerfile
有一个特定的步骤,可能与测试等相关,则必须在生产模式下启用(或禁用)。
现在,让我们假设我们处于情况 2 中。我们如何将“所有内容”从 传递--env-file
到Dockerfile
?只有一种解决方案,即扩展args:
的映射docker-compose.yml
并包含您感兴趣的每个变量,例如:
DOMAIN = \'localhost\'\nENV = \'dev.env\'\nENV_NUM = 0\nARG1 = \'value 1\'\n
Run Code Online (Sandbox Code Playgroud)\n即使没有其他解决方案可以在构建时传递参数(从docker-compose
底层docker build -f Dockerfile \xe2\x80\xa6
),这也具有“声明性”的优点(只有 中提到的变量args:
才会实际传递给Dockerfile
)。
我看到的唯一缺点是您可能在运行时有不需要的额外环境变量(从底层docker-compose
到底层docker run -e \xe2\x80\xa6
),例如ENV=prod.env
.
如果这是一个问题,您可能需要".env"
像这样分割文件:
文件prod.env
:
services:\n home:\n image: home-${ENV_NUM}\n build: \n context: .\\home\n args:\n DOMAIN: "${DOMAIN}"\n ENV_NUM: "${ENV_NUM}"\n ARG1: "${ARG1}"\n networks:\n - demo-net\n env_file:\n - ${ENV}\n labels:\n - traefik.enable=true\n - traefik.http.routers.home.rule=Host(`${DOMAIN}`)\n - traefik.http.routers.home.entrypoints=web\n volumes:\n - g:\\:c:\\sharedrive\n
Run Code Online (Sandbox Code Playgroud)\n文件prod-run.env
:
DOMAIN = \'actualdomain.com\'\nENV = \'prod-run.env\'\nENV_NUM = 1\nARG1 = \'value 1\'\n
Run Code Online (Sandbox Code Playgroud)\n(假设您只想在运行时导出这两个环境变量)。
\n或者,为了更好地遵循通常的“不要重复自己”规则,请删除prod-run.env
,然后将这些值作为docker-compose
构建参数传递,如前所述:
DOMAIN = \'actualdomain.com\'\nENV_NUM = 1\n
Run Code Online (Sandbox Code Playgroud)\n并写在Dockerfile
:
args:\n DOMAIN: "${DOMAIN}"\n ENV_NUM: "${ENV_NUM}"\n
Run Code Online (Sandbox Code Playgroud)\nDockerfile
我已经在“实验会话 2”部分中给出了这些指令的示例。
(顺便说一句,很抱歉这个答案很长:)
\n我的解决方案很烦人,这就是为什么我花了这么长时间才弄清楚的原因。我的 dockerfile 在 Windows 服务器上使用 powershell,因此我必须对每个参数执行此操作:
ARG ARG1
RUN echo $env:ARG1
Run Code Online (Sandbox Code Playgroud)
这看起来相当合适,特别是因为在 Windows 服务器上使用 Windows 容器不是我的第一选择,所以如果您遇到 env 文件等问题,请查看 @ErikMD 的答案。
归档时间: |
|
查看次数: |
9907 次 |
最近记录: |