问题描述
我有以下 Dockerfile:
FROM ubuntu:bionic
RUN apt-get update
RUN apt-get -y install curl
RUN apt-get install sudo
# Install Miniconda
ENV PATH="/root/miniconda3/bin:${PATH}"
ARG PATH="/root/miniconda3/bin:${PATH}"
RUN apt-get install -y wget && rm -rf /var/lib/apt/lists/*
RUN wget \
https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh \
&& mkdir /root/.conda \
&& bash Miniconda3-latest-Linux-x86_64.sh -b \
&& rm -f Miniconda3-latest-Linux-x86_64.sh
RUN conda --version
## Install Docker
RUN sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
lsb-release
RUN sudo apt-get install gnupg
RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
RUN echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
RUN sudo apt-get update
RUN sudo apt-get install docker-ce docker-ce-cli containerd.io -y
RUN pip install gevent
workdir /mnt
我使用以下命令运行该图像:
docker run -v /some/dir:/mnt \
-v /var/run/docker.sock:/var/run/docker.sock -it <image_tag> /bin/bash
进入图像后:
docker run -d -p 8501:8501 -v /path/to/model:/models tensorflow/serving
但是当我尝试这样做时
curl -v http://localhost:8501/v1/models/model
我明白了:
curl: (7) Failed to connect to localhost port 8501: Connection refused
那么我应该如何运行这两个容器,以便能够针对其中一个运行 curl
?
解决方法
这与两个容器需要相互通信的任何其他设置的工作方式相同:它们都需要在同一个(非默认)Docker 网络上,并且一个可以使用另一个的 docker run --name
作为DNS 名称。一个容器启动另一个无关紧要。
更广泛地说,这与 Docker 守护进程位于“其他地方”的任何其他设置的工作方式相同;也许您已将 $DOCKER_HOST
设置为指向在 VM 中运行的 Docker,或者完成了在远程主机上使用双向 TLS 身份验证设置 Docker 的工作。 docker run -v
选项是指 Docker 守护进程运行所在的主机系统路径; docker run -p
选项在运行 Docker 守护进程的主机上发布端口。在您的情况下,您正在容器的网络空间中调用 localhost
,但这与 Docker 守护程序的网络空间不同,因此您无法通过这种方式访问另一个容器。
由于您需要了解有关主机系统环境的大量详细信息,因此您需要将这些信息传递给启动容器,可能作为环境变量。使用 the Python Docker client library,例如:
import os
import docker
import requests
if __name__ == '__main__':
shared_host_path = os.environ['SHARED_HOST_PATH']
docker_network = os.environ['DOCKER_NETWORK']
client = docker.from_env()
container = client.containers.run('tensorflow/serving',detach=True,network=docker_network,name='tensorflow',volumes={shared_host_path: {'bind': '/models'}}
)
requests.get('http://tensorflow:8501/v1/models/model')
您必须在启动容器时将这些详细信息传递到容器中:
sudo docker network create some-network
sudo docker run -d \
--net some-network \
-e DOCKER_NETWORK=some-network \
-e SHARED_HOST_PATH=/path/to/model \
-v /path/to/model:/mnt \
-v /var/run/docker.sock:/var/run/docker.sock \
your-image
这设置起来很尴尬,它非常特定于 Docker(它不能在 Kubernetes 或其他编排器中工作),并且它需要管理员权限(任何可以访问 Docker 套接字的东西都可以轻松地根主机)。我发现这种方法对某些类型的集成测试很有用。更典型的模式是创建一个可以通过 HTTP 或作业队列接受请求的长时间运行的进程,以及可以向其发送请求的第二个进程。您可以在没有 Docker 的情况下构建和测试它,然后当您想在容器中运行它时,您可以使用普通的 Docker 网络,无需任何特殊权限或复杂的设置。