如何从 docker-compose 传递端口号并在 Entrypoint 中使用它?
How to pass Port number from docker-compose and use it in Entrypoint?
我想针对同一个镜像构建一个镜像和 运行 多个容器,容器 运行 在不同的端口上连接
我有以下 docker 文件
FROM python:3.9
ARG port
RUN mkdir /code
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./mock_s /code/mock_s
ENTRYPOINT ["uvicorn", "mock_s.main:app", "--port", "$port"]
和docker组成文件
version: "3"
services:
mock-server-1:
container_name: mock-s1
build:
context: .
args:
port: ${MOCK_SERVER_HOST_PORT_1}
ports:
- "${MOCK_SERVER_HOST_PORT_1}:8003"
为简洁起见,我没有显示 mock-server-2、3 等的代码。但它仅在引用端口变量 ${MOCK_SERVER_HOST_PORT_1}、${MOCK_SERVER_HOST_PORT_2} 等时有所不同
.env 文件是
MOCK_SERVER_HOST_PORT_1=8003
MOCK_SERVER_HOST_PORT_2=8004
但是在 docker compose up
我得到以下错误
Error: Invalid value for '--port': '${port}' is not a valid integer.
这表示当容器不是 运行 时 ${port}
不会扩展。
想知道这里可能有什么问题吗?
所以问题在于 Entrypoint 的工作方式。
有两种模式exec和shell形式()
默认情况下它运行处于没有变量替换的执行模式
所以要替换变量需要 运行 shell 作为入口点而不是“你的”exe
这就是我所做的
ENTRYPOINT ["sh", "-c","uvicorn mock_sfapp.main:app --port ${SERVER_PORT}"]
该设置中的另一个问题是 ${port}
的替换,它是 dockerfile 中的 ARG 似乎不起作用,
需要设置一个 ENV 变量来解决这个问题。
像这样ENV SERVER_PORT=$port
选择一个端口号并将其硬编码在 Docker 文件中是最简单和绝对安全的。
# do not pass an ARG port
EXPOSE 8000 # optional but considered good practice
CMD ["uvicorn", "mock_s.main:app", "--port", "8000"]
在您的 Compose 设置中,第二个 ports:
数字必须是固定的容器端口 8000,但第一个主机端口可以是任何您想要的。
version: "3.8"
services:
mock-server-1:
build: .
ports:
- "${MOCK_SERVER_HOST_PORT_1}:8000" # 2nd number matches fixed number in image
如果你在容器之间连接,Compose 服务名可以用作主机名,你总是使用固定的端口;不考虑或不需要撰写 ports:
。每个容器在内部都有自己的 IP 地址,如果您有多个服务恰好在同一端口上侦听,这不是问题。
version: '3.8'
services:
mock-server-1:
build: ./server1
ports: ['8001:8000'] # listens on port 8000 internally
mock-server-2:
build: ./server2
ports: ['8002:8000'] # also listens on port 8000 internally
environment:
- SERVER_1_URL=http://mock-server-1:8000
一般来说,您不应该将 Dockerfile ARG
用于您可能需要在部署时更改的任何内容,尤其是对于 Docker 可以重新映射的内容容器资源到别的东西。因此,您可能不应该将 ARG
用于端口(Compose ports:
可以重新映射它们)、用户 ID (user:
) 或文件系统路径 (volumes:
)。
我想针对同一个镜像构建一个镜像和 运行 多个容器,容器 运行 在不同的端口上连接
我有以下 docker 文件
FROM python:3.9
ARG port
RUN mkdir /code
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./mock_s /code/mock_s
ENTRYPOINT ["uvicorn", "mock_s.main:app", "--port", "$port"]
和docker组成文件
version: "3"
services:
mock-server-1:
container_name: mock-s1
build:
context: .
args:
port: ${MOCK_SERVER_HOST_PORT_1}
ports:
- "${MOCK_SERVER_HOST_PORT_1}:8003"
为简洁起见,我没有显示 mock-server-2、3 等的代码。但它仅在引用端口变量 ${MOCK_SERVER_HOST_PORT_1}、${MOCK_SERVER_HOST_PORT_2} 等时有所不同
.env 文件是
MOCK_SERVER_HOST_PORT_1=8003
MOCK_SERVER_HOST_PORT_2=8004
但是在 docker compose up
我得到以下错误
Error: Invalid value for '--port': '${port}' is not a valid integer.
这表示当容器不是 运行 时 ${port}
不会扩展。
想知道这里可能有什么问题吗?
所以问题在于 Entrypoint 的工作方式。
有两种模式exec和shell形式(
默认情况下它运行处于没有变量替换的执行模式
所以要替换变量需要 运行 shell 作为入口点而不是“你的”exe
这就是我所做的
ENTRYPOINT ["sh", "-c","uvicorn mock_sfapp.main:app --port ${SERVER_PORT}"]
该设置中的另一个问题是 ${port}
的替换,它是 dockerfile 中的 ARG 似乎不起作用,
需要设置一个 ENV 变量来解决这个问题。
像这样ENV SERVER_PORT=$port
选择一个端口号并将其硬编码在 Docker 文件中是最简单和绝对安全的。
# do not pass an ARG port
EXPOSE 8000 # optional but considered good practice
CMD ["uvicorn", "mock_s.main:app", "--port", "8000"]
在您的 Compose 设置中,第二个 ports:
数字必须是固定的容器端口 8000,但第一个主机端口可以是任何您想要的。
version: "3.8"
services:
mock-server-1:
build: .
ports:
- "${MOCK_SERVER_HOST_PORT_1}:8000" # 2nd number matches fixed number in image
如果你在容器之间连接,Compose 服务名可以用作主机名,你总是使用固定的端口;不考虑或不需要撰写 ports:
。每个容器在内部都有自己的 IP 地址,如果您有多个服务恰好在同一端口上侦听,这不是问题。
version: '3.8'
services:
mock-server-1:
build: ./server1
ports: ['8001:8000'] # listens on port 8000 internally
mock-server-2:
build: ./server2
ports: ['8002:8000'] # also listens on port 8000 internally
environment:
- SERVER_1_URL=http://mock-server-1:8000
一般来说,您不应该将 Dockerfile ARG
用于您可能需要在部署时更改的任何内容,尤其是对于 Docker 可以重新映射的内容容器资源到别的东西。因此,您可能不应该将 ARG
用于端口(Compose ports:
可以重新映射它们)、用户 ID (user:
) 或文件系统路径 (volumes:
)。