Невозможно выполнить команду в контейнере Ubuntu из контейнера Airflow с помощью DockerOperator

#docker #ubuntu #docker-compose #airflow #dockeroperator

#docker #ubuntu #docker-compose #воздушный поток #dockeroperator

Вопрос:

Я очень новичок в Docker Airflow. Ниже приведено то, что я пытаюсь выполнить.

У меня есть 4 службы, как показано в приведенном ниже файле компоновки. 3 относятся к Airflow, а один — к тестовому экземпляру Ubuntu. Контейнеры, связанные с Airflow: airflow-database , airflow-webserver , airflow-scheduler могут взаимодействовать друг с другом, и я могу запускать примеры баз данных. Теперь я добавил 4-ю службу (ubuntu), которой я пытаюсь отправить простую команду «/ bin / sleep 10» из DAG с помощью DockerOperator (ниже приведен файл DAG). Но по какой-то причине я получаю сообщение об отказе в разрешении (также прилагается файл с ошибкой DAG).

Это работает, если я запускаю Airflow с локального хоста, а не из контейнера docker, который не может понять, чего мне не хватает. Ниже приведены некоторые из способов, которые я пробовал:

  • В docker_url:
  1. заменено unix://var/run/docker.sock на tcp://172.20.0.1 то, что он сможет разрешить через IP-адрес хоста docker
  2. используется gateway.host.internal
  3. Даже удалил параметр docker_url у оператора, но понял, что он в любом случае по умолчанию устанавливается в unix://var/run/docker.sock
  4. Пробовал кучу комбинаций, tcp: // 172.20.0.1: 2376, tcp: // 172.20.0.1: 2375
  5. Сопоставленный порт хоста с Ubuntu, например 8085: 8085 и т.д.
  • Может быть, пользователь airflow веб-сервера Airflow выгнан Ubuntu
  • Итак, создал группу в контейнере Ubuntu и добавил в нее пользователя airflow — Нет, тоже не сработало
  • api_version: опция «авто» также не работает и продолжает выдавать ошибку «Версия не найдена». Поэтому пришлось жестко запрограммировать 1.41, поскольку я нашел это в docker version команде. Не уверен, что это то, что должно быть.

Заранее спасибо за любую помощь в том, что еще я могу попытаться сделать, чтобы это сработало 🙂

docker-compose.yml

 version: '3.2'

services:
# Ubuntu Container  
  ubuntu:
    image: ubuntu
    networks:
      - mynetwork

# Airflow Database
  airflow-database:
    image: postgres:12
    env_file:
      - .env
    ports:
      - 5432:5432
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./airflow/database/data:/var/lib/postgresql/data/pgdata
      - ./airflow/database/logs:/var/lib/postgresql/data/log
    command: >
     postgres
       -c listen_addresses=*
       -c logging_collector=on
       -c log_destination=stderr
       -c max_connections=200
    networks:
      - mynetwork

# Airflow DB Init
  initdb:
      image: apache/airflow:2.0.0-python3.8
      env_file:
        - .env
      depends_on:
        - airflow-database
      volumes:
        - /var/run/docker.sock:/var/run/docker.sock
        - ./airflow/metadata-airflow/dags:/opt/airflow/dags
        - ./airflow/logs:/opt/airflow/logs
      entrypoint: /bin/bash
      command: -c "airflow db init amp;amp; airflow users create --firstname admin --lastname admin --email admin@admin.com --password admin --username admin --role Admin"
      networks:
        - mynetwork

# Airflow Webserver
  airflow-webserver:
    image: apache/airflow:2.0.0-python3.8
    env_file:
      - .env
    depends_on:
      - airflow-database
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./airflow/metadata-airflow/dags:/opt/airflow/dags
      - ./airflow/logs:/opt/airflow/logs
    ports:
      - 8080:8080
    deploy:
      restart_policy:
        condition: on-failure
        delay: 8s
        max_attempts: 3
    command: webserver
    healthcheck:
      test: ["CMD-SHELL", "[ -f /opt/airflow/airflow-webserver.pid ]"]
      interval: 30s
      timeout: 30s
      retries: 3
    networks:
      - mynetwork

# Airflow Scheduler
  airflow-scheduler:
    image: apache/airflow:2.0.0-python3.8
    env_file:
      - .env
    depends_on:
      - airflow-database
      - airflow-webserver
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./airflow/metadata-airflow/dags:/opt/airflow/dags
      - ./airflow/logs:/opt/airflow/logs
    deploy:
      restart_policy:
        condition: on-failure
        delay: 8s
        max_attempts: 3
    command: scheduler
    networks:
      - mynetwork

networks:
  mynetwork:
 

Файл DAG

 from datetime import timedelta
from airflow import DAG
from airflow.operators.bash_operator import BashOperator
from airflow.providers.docker.operators.docker import DockerOperator
from airflow.utils.dates import days_ago


default_args = {
    'owner': 'airflow',
    'depends_on_past': False,
    'email': ['airflow@example.com'],
    'email_on_failure': False,
    'email_on_retry': False,
}

dag = DAG(
    'docker_sample',
    default_args=default_args,
    schedule_interval=None,
    start_date=days_ago(2),
)

t1 = DockerOperator(
    task_id='docker_op_tester',
    api_version='auto', 
    image='ubuntu',
    docker_url='unix://var/run/docker.sock',
    auto_remove=True,
    command=[
        "/bin/bash",
        "-c",
        "/bin/sleep 30; "],
    network_mode='bridge',
    dag=dag,
)


t1
 

Журнал ошибок базы данных

 *** Reading local file: /opt/airflow/logs/docker_sample/docker_op_tester/2021-01-09T05:16:17.174981 00:00/1.log
[2021-01-09 05:16:26,726] {taskinstance.py:826} INFO - Dependencies all met for <TaskInstance: docker_sample.docker_op_tester 2021-01-09T05:16:17.174981 00:00 [queued]>
[2021-01-09 05:16:26,774] {taskinstance.py:826} INFO - Dependencies all met for <TaskInstance: docker_sample.docker_op_tester 2021-01-09T05:16:17.174981 00:00 [queued]>
[2021-01-09 05:16:26,775] {taskinstance.py:1017} INFO - 
--------------------------------------------------------------------------------
[2021-01-09 05:16:26,776] {taskinstance.py:1018} INFO - Starting attempt 1 of 1
[2021-01-09 05:16:26,776] {taskinstance.py:1019} INFO - 
--------------------------------------------------------------------------------
[2021-01-09 05:16:26,790] {taskinstance.py:1038} INFO - Executing <Task(DockerOperator): docker_op_tester> on 2021-01-09T05:16:17.174981 00:00
[2021-01-09 05:16:26,794] {standard_task_runner.py:51} INFO - Started process 1057 to run task
[2021-01-09 05:16:26,817] {standard_task_runner.py:75} INFO - Running: ['airflow', 'tasks', 'run', 'docker_sample', 'docker_op_tester', '2021-01-09T05:16:17.174981 00:00', '--job-id', '360', '--pool', 'default_pool', '--raw', '--subdir', 'DAGS_FOLDER/example_docker.py', '--cfg-path', '/tmp/tmp4phq52dv']
[2021-01-09 05:16:26,821] {standard_task_runner.py:76} INFO - Job 360: Subtask docker_op_tester
[2021-01-09 05:16:26,932] {logging_mixin.py:103} INFO - Running <TaskInstance: docker_sample.docker_op_tester 2021-01-09T05:16:17.174981 00:00 [running]> on host 367f0fc7d092
[2021-01-09 05:16:27,036] {taskinstance.py:1230} INFO - Exporting the following env vars:
AIRFLOW_CTX_DAG_EMAIL=airflow@example.com
AIRFLOW_CTX_DAG_OWNER=airflow
AIRFLOW_CTX_DAG_ID=docker_sample
AIRFLOW_CTX_TASK_ID=docker_op_tester
AIRFLOW_CTX_EXECUTION_DATE=2021-01-09T05:16:17.174981 00:00
AIRFLOW_CTX_DAG_RUN_ID=manual__2021-01-09T05:16:17.174981 00:00
[2021-01-09 05:16:27,054] {taskinstance.py:1396} ERROR - ('Connection aborted.', PermissionError(13, 'Permission denied'))
Traceback (most recent call last):
  File "/home/airflow/.local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 670, in urlopen
    httplib_response = self._make_request(
  File "/home/airflow/.local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 392, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/usr/local/lib/python3.8/http/client.py", line 1255, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/local/lib/python3.8/http/client.py", line 1301, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/local/lib/python3.8/http/client.py", line 1250, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/local/lib/python3.8/http/client.py", line 1010, in _send_output
    self.send(msg)
  File "/usr/local/lib/python3.8/http/client.py", line 950, in send
    self.connect()
  File "/home/airflow/.local/lib/python3.8/site-packages/docker/transport/unixconn.py", line 43, in connect
    sock.connect(self.unix_socket)
PermissionError: [Errno 13] Permission denied

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/airflow/.local/lib/python3.8/site-packages/requests/adapters.py", line 439, in send
    resp = conn.urlopen(
  File "/home/airflow/.local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 726, in urlopen
    retries = retries.increment(
  File "/home/airflow/.local/lib/python3.8/site-packages/urllib3/util/retry.py", line 410, in increment
    raise six.reraise(type(error), error, _stacktrace)
  File "/home/airflow/.local/lib/python3.8/site-packages/urllib3/packages/six.py", line 734, in reraise
    raise value.with_traceback(tb)
  File "/home/airflow/.local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 670, in urlopen
    httplib_response = self._make_request(
  File "/home/airflow/.local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 392, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/usr/local/lib/python3.8/http/client.py", line 1255, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/local/lib/python3.8/http/client.py", line 1301, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/local/lib/python3.8/http/client.py", line 1250, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/local/lib/python3.8/http/client.py", line 1010, in _send_output
    self.send(msg)
  File "/usr/local/lib/python3.8/http/client.py", line 950, in send
    self.connect()
  File "/home/airflow/.local/lib/python3.8/site-packages/docker/transport/unixconn.py", line 43, in connect
    sock.connect(self.unix_socket)
urllib3.exceptions.ProtocolError: ('Connection aborted.', PermissionError(13, 'Permission denied'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/airflow/.local/lib/python3.8/site-packages/airflow/models/taskinstance.py", line 1086, in _run_raw_task
    self._prepare_and_execute_task_with_callbacks(context, task)
  File "/home/airflow/.local/lib/python3.8/site-packages/airflow/models/taskinstance.py", line 1260, in _prepare_and_execute_task_with_callbacks
    result = self._execute_task(context, task_copy)
  File "/home/airflow/.local/lib/python3.8/site-packages/airflow/models/taskinstance.py", line 1300, in _execute_task
    result = task_copy.execute(context=context)
  File "/home/airflow/.local/lib/python3.8/site-packages/airflow/providers/docker/operators/docker.py", line 286, in execute
    if self.force_pull or not self.cli.images(name=self.image):
  File "/home/airflow/.local/lib/python3.8/site-packages/docker/api/image.py", line 89, in images
    res = self._result(self._get(self._url("/images/json"), params=params),
  File "/home/airflow/.local/lib/python3.8/site-packages/docker/utils/decorators.py", line 46, in inner
    return f(self, *args, **kwargs)
  File "/home/airflow/.local/lib/python3.8/site-packages/docker/api/client.py", line 230, in _get
    return self.get(url, **self._set_request_timeout(kwargs))
  File "/home/airflow/.local/lib/python3.8/site-packages/requests/sessions.py", line 543, in get
    return self.request('GET', url, **kwargs)
  File "/home/airflow/.local/lib/python3.8/site-packages/requests/sessions.py", line 530, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/airflow/.local/lib/python3.8/site-packages/requests/sessions.py", line 643, in send
    r = adapter.send(request, **kwargs)
  File "/home/airflow/.local/lib/python3.8/site-packages/requests/adapters.py", line 498, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', PermissionError(13, 'Permission denied'))
[2021-01-09 05:16:27,073] {taskinstance.py:1433} INFO - Marking task as FAILED. dag_id=docker_sample, task_id=docker_op_tester, execution_date=20210109T051617, start_date=20210109T051626, end_date=20210109T051627
[2021-01-09 05:16:27,136] {local_task_job.py:118} INFO - Task exited with return code 1
 

Технические характеристики:
Docker:
Версия: 20.10.2
Версия API: 1.41

Изображение воздушного потока: apache / airflow: 2.0.0-python3.8

Хост-система: macOS BigSur

Ответ №1:

Я думаю, что я понял — источник: https://tomgregory.com/running-docker-in-docker-on-windows

  1. Проверьте идентификатор группы root:

    запуск docker — rm -v /var/run/docker.sock:/var/run/docker.sock debian: статистика buster-slim -c %g /var/run/docker.sock

возвращает «1001» для меня.

  1. Добавьте операторы group_add, ссылающиеся на этот идентификатор группы, в ваш docker-compose.yml:
      image: apache/airflow:2.0.0-python3.8
     group_add:
       - 1001
     

Я добавил его на веб-сервер и планировщик (не уверен, нужно ли это обоим), и, похоже, он работает для меня сейчас (по крайней мере, он выходит из строя позже;-)

Редактировать:

вам также необходимо добавить

 AIRFLOW__CORE__ENABLE_XCOM_PICKLING=True
 

как переменная среды в Airflow, в противном случае ваш контейнер вылетает при выходе (https://github.com/apache/airflow/issues/13487 ).

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

1. привет, спасибо за публикацию. Я борюсь с этой ошибкой: File "/home/airflow/.local/lib/python3.6/site-packages/docker/transport/unixconn.py", line 43, in connect sock.connect(self.unix_socket) FileNotFoundError: [Errno 2] No such file or directory я попытался добавить group_add результат из docker run предложенной вами команды и добавил этот AIRFLOW__CORE__ env var в docker-compose. yaml, но это не помогло. все еще сбой в том же месте. есть еще идеи?

2. наконец-то я получил другое сообщение об ошибке: File"/home/airflow/.local/lib/python3.6/site-packages/docker/transport/unixconn.py", line 43, in connect sock.connect(self.unix_socket) PermissionError: [Errno 13] Permission denied ; ошибка такая же, как у вас. Я последовал вашим предложениям. Какие-либо другие трюки попробовать?

3. Спасибо! Это помогло мне решить эту проблему, с которой я застрял на три недели.

Ответ №2:

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: не решение производственного уровня.

Это немного поздно, но вот что я сделал, чтобы решить эту проблему.

В тех же строках, что и @lungben, я узнал, что это связано с конфликтом доступа к файлам между группой пользователей демона docker, запущенного на хосте, и той, которая работает внутри контейнеров.

На моем Mac (локальном): Я запустил контейнеры, предоставив пользователю airflow (внутри контейнеров) корневые привилегии (AIRFLOW_UID = 0 и AIRFLOW_GID = 0), в основном такие же, как корень локального компьютера. (НЕТ, НЕТ для производства). Попытался добавить мое имя пользователя Mac в группу docker, но по какой-то причине это не сработало.

На сервере Ubuntu:

  • Добавлен пользователь ubuntu в группу docker sudo usermod -aG docker $USER (создать, если группа docker не существует)
  • Если это не устраняется, chmod 777 the /var/run/docker.sock amp; запустите docker compose как sudo (опять NONO в производстве)

Поскольку я больше не использую DockerOperator, откатил все вышеуказанные изменения.