как выполнить команду docker изнутри docker контейнера на windows хосте - PullRequest
0 голосов
/ 17 января 2020

Ситуация следующая: я успешно, локально разработал супер простой процесс ETL, который извлекает данные из некоторого удаленного местоположения, а затем записывает эти необработанные данные в контейнер MongoDB на моей локальной машине Windows. Теперь я хочу запланировать этот процесс с Apache -Airflow, используя DockerOperator для каждой задачи, т.е. я хочу создать docker образ моего исходного кода, а затем выполнить исходный код в этом образе с помощью DockerOperator. Поскольку я работаю на машине Windows, я могу использовать только Airflow из контейнера docker для фактического запуска Airflow DAG. Контейнер Airflow (называемый ниже веб-сервером) и контейнер Mon go (называемый mon go ниже) указаны в файле docker-compose.yml, который можно увидеть в конце.

В меру лучшего насколько мне известно, каждый раз, когда запускается моя простая группа ETL DAG и выполняется DockerOperator, контейнер «веб-сервер» создает новый «одноуровневый» контейнер для каждой задачи ETL, затем выполняется исходный код внутри этого нового контейнера и после завершения задачи , этот новый контейнер снова удален. Если мое понимание верно до этого момента, контейнер веб-сервера должен иметь возможность выполнять docker команды, такие как, например, docker build..., чтобы иметь возможность создавать эти одноуровневые контейнеры.

Чтобы проверить эту теорию, я добавил тома /var/run/docker.sock:/var/run/docker.sock и /usr/bin/docker:/usr/bin/docker в определение контейнера веб-сервера в файле docker-compose.yml, чтобы контейнер веб-сервера мог использовать демон docker на моем хосте. (windows) машина. Затем я запустил веб-сервер и контейнеры mon go, используя docker-compose up -d, я вошел в контейнер веб-сервера, используя docker exec -it <name_of_webserver_container> /bin/bash, а затем попробовал простую команду docker docker ps --all. Однако вывод этой команды был bash: docker: command not found. Таким образом, похоже, что Docker не был правильно установлен внутри контейнера веб-сервера. Как я могу убедиться, что Docker установлен внутри контейнера веб-сервера, чтобы можно было создавать другие одноуровневые контейнеры?

Ниже вы можете найти соответствующие аспекты файла docker-compose.yml и Dockerfile, используемых для контейнер веб-сервера.

docker-compose.yml, расположенный в каталоге проекта root:

webserver:
        build: ./docker-airflow
        restart: always
        privileged: true
        depends_on:
            - postgres  # some other service I cut out from this post
            - mongo
            - mongo-express  # some other service I cut out from this post
        environment:
            - LOAD_EX=n
            - EXECUTOR=Local
            - POSTGRES_USER=some_user
            - POSTGRES_PASSWORD=some_pw
            - POSTGRES_DB=airflowdb
        volumes:
            # DAG folder
            - ./docker-airflow/dags:/usr/local/airflow/dags
            # Add path for external python modules
            - ./src:/home/python_modules
            # Add path for airflow workspace folder
            - ./docker-airflow/workdir:/home/workdir
            # Mount the docker socket from the host (currently my laptop) into the webserver container
            - //var/run/docker.sock:/var/run/docker.sock  # double // are necessary for windows host
        ports:
            # Change port to 8081 to avoid Jupyter conflicts
            - 8081:8080
        command: webserver
        healthcheck:
            test: ["CMD-SHELL", "[ -f /usr/local/airflow/airflow-webserver.pid ]"]
            interval: 30s
            timeout: 30s
            retries: 3
        networks:
            - mynet

Dockerfile для контейнера веб-сервера, расположенного в папке docker-airflow:

FROM puckel/docker-airflow:1.10.4

# Adds DAG folder to the PATH
ENV PYTHONPATH "${PYTHONPATH}:/home/python_modules:/usr/local/airflow/dags"

# Install the optional packages and change the user to airflow again
COPY requirements.txt requirements.txt
USER root
RUN pip install -r requirements.txt

# Install docker inside the webserver container
RUN pip install -U pip && pip install docker
ENV SHARE_DIR /usr/local/share

# Install simple text editor for debugging
RUN ["apt-get", "update"]
RUN ["apt-get", "-y", "install", "vim"]

USER airflow

РЕДАКТИРОВАТЬ / Обновить :

После включения комментариев Но я изменил Dockerfile контейнера веб-сервера на следующее:

FROM puckel/docker-airflow:1.10.4

# Adds DAG folder to the PATH
ENV PYTHONPATH "${PYTHONPATH}:/home/python_modules:/usr/local/airflow/dags"

# Install the optional packages and change the user to airflow again
COPY requirements.txt requirements.txt
USER root
RUN pip install -r requirements.txt

# Install docker inside the webserver container
RUN curl -sSL https://get.docker.com/ | sh
ENV SHARE_DIR /usr/local/share

# Install simple text editor for debugging
RUN ["apt-get", "update"]
RUN ["apt-get", "-y", "install", "vim"]

USER airflow

и добавил docker==4.1.0 в файл requirements.txt (на который есть ссылка в приведенном выше Dockerfile), который содержит все устанавливаемые пакеты внутри контейнера веб-сервера.

Однако теперь, когда я сначала запускаю службы с docker-compose up --build -d, затем вхожу в контейнер веб-сервера, например, docker exec -it <name_of_webserver_container> /bin/bash, а затем введите простую команду docker docker ps --all, я получаю следующий вывод:

Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.40/containers/json?all=1: dial unix /var/run/docker.sock: connect: permission denied

Похоже, мне все еще нужно предоставить некоторые права / привилегии, которые я нахожу непонятными, потому что в разделе веб-сервера файла docker-compose.yml я уже поместил privileged: true. Так кто-нибудь знает причину этой проблемы?

РЕДАКТИРОВАТЬ / ОБНОВИТЬ / ОТВЕТ

После удаления USER airlfow из Dockerfile контейнера веб-сервера, я могу docker команды внутри контейнера веб-сервера!

1 Ответ

1 голос
/ 17 января 2020

То, что вы пытаетесь сделать, называется docker в docker.

Вам необходимо сделать следующее:

  • установить клиент docker в контейнер

Добавить RUN curl -sSL https://get.docker.com/ | sh

  • смонтировать docker сокет

Вы сделали это хорошо смонтировать //var/run/docker.sock:/var/run/docker.sock

  • запустить свой контейнер в привилегированном режиме

Добавить privileged: true в свой контейнер

В вашем конкретном c случае вам необходимо выполнить следующие действия:

  • Удалить RUN pip install -U pip && pip install docker, поскольку мы уже установили его
  • Удалить USER airflow, вам нужно использовать значение по умолчанию пользователь или root пользователь
  • Добавьте docker==4.1.0 к Requirements.txt
...