【问题标题】:Run webserver on Docker in Docker在 Docker 中的 Docker 上运行 webserver
【发布时间】:2021-07-29 05:26:10
【问题描述】:

我有以下 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

【问题讨论】:

  • 您需要创建一个host 类型的网络并使用docker network connectdocker run --network=my-net etc... 运行连接到该网络的容器

标签: docker docker-in-docker


【解决方案1】:

这与两个容器需要相互通信的任何其他设置的工作方式相同:它们都需要在同一个(非默认)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 套接字的人都可以轻松地 root 主机)。我发现这种方法对某些类型的集成测试很有用。更典型的模式是创建一个可以通过 HTTP 或作业队列接受请求的长时间运行的进程,以及可以向其发送请求的第二个进程。你可以在没有 Docker 的情况下构建和测试它,然后当你想在容器中运行它时,你可以使用普通的 Docker 网络,无需任何特殊权限或复杂设置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-22
    • 2017-12-18
    • 2019-07-22
    • 1970-01-01
    • 2019-04-14
    • 1970-01-01
    • 2016-11-25
    • 1970-01-01
    相关资源
    最近更新 更多