简体   繁体   English

在 Docker 中的 Docker 上运行 webserver

[英]Run webserver on Docker in Docker

I have the following Dockerfile:我有以下 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

I run that image with:我运行该图像:

docker run -v /some/dir:/mnt \
    -v /var/run/docker.sock:/var/run/docker.sock -it <image_tag> /bin/bash

Once inside the image I do:一旦进入图像,我会:

docker run -d -p 8501:8501 -v /path/to/model:/models tensorflow/serving 

but when I attempt to then do但是当我尝试这样做时

curl -v http://localhost:8501/v1/models/model

I get:我得到:

curl: (7) Failed to connect to localhost port 8501: Connection refused

So how should I be running these two containers in order to be able to run curl against one of them?那么我应该如何运行这两个容器才能对其中一个运行curl呢?

This works the same way as any other setup where two containers need to communicate with each other: they both need to be on the same (non-default) Docker network, and one can use the other's docker run --name as a DNS name.这与两个容器需要相互通信的任何其他设置的工作方式相同:它们都需要在同一个(非默认)Docker 网络上,并且一个可以使用另一个的docker run --name as a ZED5F2BDECBD4BD349D09466 . It doesn't matter that one container started the other.一个容器启动另一个容器并不重要。

More broadly, this works the same way as any other setup where the Docker daemon is "somewhere else";更广泛地说,这与 Docker 守护进程位于“其他地方”的任何其他设置的工作方式相同; maybe you've set $DOCKER_HOST to point at Docker running in a VM, or done the work to set up Docker with mutual TLS authentication on a remote host.也许您已将$DOCKER_HOST设置为指向在 VM 中运行的 Docker,或者完成了在远程主机上使用双向 TLS 身份验证设置 Docker 的工作。 docker run -v options refer to host-system paths where the Docker daemon is running ; docker run -v选项指的是运行 Docker 守护程序的主机系统路径; docker run -p options publish ports on the host where the Docker daemon is running . docker run -p选项在运行 Docker 守护程序的主机上发布端口。 In your case you're making a call to localhost in the container's network space, but that's different from the Docker daemon's network space, so you can't reach the other container this way.在您的情况下,您正在容器的网络空间中调用localhost ,但这与 Docker 守护程序的网络空间不同,因此您无法通过这种方式访问其他容器。

Since you need to know a lot of details about the host-system environment, you need to pass these to the launching container, perhaps as environment variables.由于您需要了解有关主机系统环境的许多详细信息,因此您需要将这些信息传递给启动容器,可能作为环境变量。 Using the Python Docker client library , for example:使用Python Docker 客户端库,例如:

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')

You'd have to pass these details into the container when you launch it:启动容器时,您必须将这些详细信息传递到容器中:

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

This is awkward to set up, it is very Docker-specific (it will not work in Kubernetes or other orchestrators), and it requires administrator privileges (anything with access to the Docker socket can trivially root the host).这设置起来很尴尬,它是非常特定于 Docker 的(它在 Kubernetes 或其他编排器中不起作用),并且它需要管理员权限(任何可以访问 Docker 套接字的人都可以轻松地启动主机)。 I've found this approach useful for some types of integration testing.我发现这种方法对某些类型的集成测试很有用。 A more typical pattern is to create a long-running process that can accept requests via HTTP or a job queue, and a second process that can send it requests.更典型的模式是创建一个可以通过 HTTP 或作业队列接受请求的长时间运行的进程,以及可以向其发送请求的第二个进程。 You can build and test this without Docker, and then when you want to run it in containers you can use normal Docker networking, without any special privileges or complex setup.您可以在没有 Docker 的情况下构建和测试它,然后当您想在容器中运行它时,您可以使用普通的 Docker 网络,无需任何特殊权限或复杂设置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM