Docker В Docker В Docker Compose (проблемы с сетью)

#docker #docker-compose #dockerfile

#docker #docker-compose #dockerfile

Вопрос:

Я буквально не могу объяснить вам, как трудно мне разобраться в желании создать контейнер docker, в котором будет запущен docker, на котором будет запущен мой веб-сервер, который будет иметь доступ к моему внешнему хосту docker.

Итак, что я знаю на данный момент:

  • У меня есть dockerfile, который при выполнении вне docker compose и тестировании с помощью я вижу, что он подключается к моему хост-демону docker!
  • Затем я перехожу к своей настройке docker-compose и понимаю, что у меня, должно быть, проблема из-за сети, которая возникает внутри файлов docker-compose. Но у меня 0 сетевых возможностей docker-compose, поэтому я спрашиваю, как я могу также подключить свой контейнер к сети по умолчанию один раз внутри этой настройки?

Мой скрипт Bash (точка входа):

 #!/bin/sh
set -e


# first arg is `-f` or `--some-option`
if [ "${1#-}" != "$1" ]; then
    set -- docker "$@"
fi

# if our command is a valid Docker subcommand, let's invoke it through Docker instead
# (this allows for "docker run docker ps", etc)
if docker help "$1" > /dev/null 2>amp;1; then
    set -- docker "$@"
fi

# if we have "--link some-docker:docker" and not DOCKER_HOST, let's set DOCKER_HOST automatically
if [ -z "$DOCKER_HOST" -a "$DOCKER_PORT_2375_TCP" ]; then
    export DOCKER_HOST='tcp://docker:2375'
fi

if [ "$1" = 'dockerd' ]; then
    cat >amp;2 <<-'EOW'
        📎 Hey there!  It looks like you're trying to run a Docker daemon.
           You probably should use the "dind" image variant instead, something like:
             docker run --privileged --name some-overlay-docker -d docker:stable-dind --storage-driver=overlay
           See https://hub.docker.com/_/docker/ for more documentation and usage examples.
    EOW
    sleep 3
fi

docker version

dotnet ApiServer.dll
  

Мой файл compose:

 version: '3.4'

services:
  apiserver:
    image: ${DOCKER_REGISTRY-}apiserver
    build:
      context: ./
      dockerfile: ./ApiServer/Dockerfile
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock
  

Наконец, мой dockerfile: (На самом деле это не должно быть нужно, но вот оно)

 FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-alpine AS base

COPY /ApiServer/modprobe.sh /usr/local/bin/modprobe
COPY /ApiServer/docker-entrypoint.sh /usr/local/bin/

RUN dos2unix -u /usr/local/bin/modprobe
RUN dos2unix -u /usr/local/bin/docker-entrypoint.sh

WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/core/sdk:2.2-alpine AS build
WORKDIR /src
COPY ["ApiServer/ApiServer.csproj", "ApiServer/"]
COPY ["SharedLibs/SharedLibs.csproj", "SharedLibs/"]
RUN dotnet restore "ApiServer/ApiServer.csproj"
COPY . .
WORKDIR "/src/ApiServer"
RUN dotnet build "ApiServer.csproj" -c Release -o /app

FROM build AS publish
RUN dotnet publish "ApiServer.csproj" -c Release -o /app

FROM base AS docker
## Docker Setup
RUN apk add --no-cache 
        ca-certificates

# set up nsswitch.conf for Go's "netgo" implementation (which Docker explicitly uses)
# - https://github.com/docker/docker-ce/blob/v17.09.0-ce/components/engine/hack/make.sh#L149
# - https://github.com/golang/go/blob/go1.9.1/src/net/conf.go#L194-L275
# - docker run --rm debian:stretch grep '^hosts:' /etc/nsswitch.conf
RUN [ ! -e /etc/nsswitch.conf ] amp;amp; echo 'hosts: files dns' > /etc/nsswitch.conf

ENV DOCKER_CHANNEL stable
ENV DOCKER_VERSION 18.09.3
# TODO ENV DOCKER_SHA256
# https://github.com/docker/docker-ce/blob/5b073ee2cf564edee5adca05eee574142f7627bb/components/packaging/static/hash_files !!
# (no SHA file artifacts on download.docker.com yet as of 2017-06-07 though)

RUN set -eux; 
    
# this "case" statement is generated via "update.sh"
    apkArch="$(apk --print-arch)"; 
    case "$apkArch" in 
        x86_64) dockerArch='x86_64' ;; 
        armhf) dockerArch='armel' ;; 
        aarch64) dockerArch='aarch64' ;; 
        ppc64le) dockerArch='ppc64le' ;; 
        s390x) dockerArch='s390x' ;; 
        *) echo >amp;2 "error: unsupported architecture ($apkArch)"; exit 1 ;;
    esac; 
    
    if ! wget -O docker.tgz "https://download.docker.com/linux/static/${DOCKER_CHANNEL}/${dockerArch}/docker-${DOCKER_VERSION}.tgz"; then 
        echo >amp;2 "error: failed to download 'docker-${DOCKER_VERSION}' from '${DOCKER_CHANNEL}' for '${dockerArch}'"; 
        exit 1; 
    fi; 
    
    tar --extract 
        --file docker.tgz 
        --strip-components 1 
        --directory /usr/local/bin/ 
    ; 
    rm docker.tgz; 
    
    dockerd --version; 
    docker --version

FROM docker AS final
WORKDIR /app
COPY --from=publish /app .

ENTRYPOINT ["../usr/local/bin/docker-entrypoint.sh"]
  

Ответ №1:

Ваш Dockerfile предоставляет порт 80, но вы не отображаете его в своем docker-compose.yml файле.

Попробуйте обновить docker-compose-yml файл следующим образом:

docker-compose-yml

 version: '3.4'

services:
  apiserver:
    image: ${DOCKER_REGISTRY-}apiserver
    build:
      context: ./
      dockerfile: ./ApiServer/Dockerfile
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock
    ports:
      - 8080:80
  

Клавиша ports отобразит порты с вашего хост-компьютера на контейнер. Упрощенный синтаксис:

     ports:
      - <hostport>:<containerport>
  

При запуске контейнера с помощью docker-compose docker создаст новую связующую сеть для вашего стека приложений. Контейнеры в этой сети недоступны с хоста, и контейнеры внутри сети также не могут обращаться к хосту. Вот почему вам нужно сопоставление портов — оно сопоставит порт 8080 на хост-компьютере с портом 80 контейнера.

Затем вы можете обратиться к открытой службе в контейнере с помощью http://localhost:8080 с хост-компьютера.

Обновить

Из вашего комментария я понял, что на хосте могут быть запущены другие службы, к которым вы хотите иметь возможность подключаться из контейнера ApiServer, например, из базы данных. Я думаю, есть одно быстрое решение этой проблемы, и это подключение нового контейнера к сети «хост».

Вы можете попробовать обновить свой файл docker-compose.yml до этого:

docker-compose-yml

 version: '3.4'

services:
  apiserver:
    image: ${DOCKER_REGISTRY-}apiserver
    build:
      context: ./
      dockerfile: ./ApiServer/Dockerfile
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock
    ports:
      - 8080:80
    network_mode: "host"
  

Результатом этого является то, что при разрешении localhost и 127.0.0.1 изнутри вашего контейнера вы фактически получите hostmachine. Однако это не сработает, если вы развернете свой контейнер в swarm.

Комментарии:

1. Итак, моя проблема в том, что мой контейнерный apiservice должен иметь возможность подключаться к хост-ОС не через сопоставление, а находиться в той же сети. Это потому, что у моего приложения в конечном итоге будет база данных и тому подобное, и поэтому сейчас оно находится внутри compose. Мой apiservice должен быть подключен к новой мостовой сети и исходной мостовой сети по умолчанию уровня хоста.

2. Если вы получаете конкретную ошибку, пожалуйста, укажите ее.

3. Проблема не в этом: / если я запускаю контейнер вне docker-compose, я получаю то, что ищу. Если я запускаю контейнер с помощью docker-compose, он просто никогда не подключается к моему демону хоста.

4. Какую команду вы используете при запуске без docker-compose?

5. Вы решили эту проблему? Могу ли я что-нибудь сделать, чтобы помочь? Была ли информация / решение полезными?