#jenkins #docker #continuous-integration #ansible #containers
#дженкинс #докер #непрерывная интеграция #ансибль #контейнеры
Вопрос:
Я интегрирую Docker в непрерывную интеграцию проекта, поэтому при каждой фиксации он создает образ docker, помещает его в частный реестр и запускает этот контейнер на компьютере, работающем в OpenStack. Мы используем Ansible (версия 2.1) для автоматизации, поэтому для взаимодействия с Docker я использую модуль docker_container . Помимо простого запуска контейнера docker, мне нужно ввести некоторые файлы конфигурации, которые различаются в зависимости от того, в какой среде я развертываю. Я использую опцию volumes для ввода файлов конфигурации.
Кажется, все работает нормально, я могу запустить развертывание несколько раз, контейнеры docker будут правильно заменены… но проблема начинается, когда тот же процесс запускается с другого хоста (например, с нашего хоста непрерывной интеграции, Jenkins CI или просто с другого ноутбука). Образ docker собран правильно, он помещается в частный реестр, но когда он пытается запустить новый контейнер, ему не удается удалить старый и он останавливается. Я получаю следующую ошибку ansible:
fatal: [host-1]: FAILED! => {"changed": false, "failed": true, "msg": "Error removing container xxxx: 500 Server Error: Internal Server Error ("Driver devicemapper failed to remove root filesystem xxx: remove /var/lib/docker/overlay/yyyy/merged: device or resource busy")"}
Я использую следующую задачу docker_container для запуска контейнера:
- name: Run the application container
docker_container:
name: "myProject-{{ environment_env }}-app"
image: "{{ docker_app_image }}"
state: started
pull: yes
restart: yes
ports:
- "80:80"
- "443:443"
volumes:
- "{{ remote_home }}/myProject_{{ environment_env }}/log:{{ log_dir }}"
- "{{ remote_home }}/myProject_{{ environment_env }}/local_settings.py:/server/cms/local_settings.py:ro"
- "{{ remote_home }}/myProject_{{ environment_env }}/nginx.conf:/etc/nginx/nginx.conf:ro"
- "{{ remote_home }}/myProject_{{ environment_env }}/myProject.pem:/etc/certificates/myProject.pem:ro"
- "{{ remote_home }}/myProject_{{ environment_env }}/myProject_private.pem:/etc/certificates/myProject_private.pem:ro"
- "{{ remote_home }}/myProject_{{ environment_env }}/myProject_vhost.conf:/etc/nginx/conf.d/myProject_vhost.conf:ro"
Я пытался изменить драйвер docker с devicemapper на overlay, но проблема остается той же. Кто-нибудь из вас сталкивался с этой проблемой раньше? Связано ли это с владельцем файла или разрешениями на другом хосте, на котором выполняется развертывание, и система docker не может справиться с этим? Любая помощь будет признательна! Спасибо.
Комментарии:
1. Работают ли команды docker (pull, stop, rm, run), если вы запускаете их из командной строки? Какую версию docker вы используете на отказавших узлах?
2. @BMitch да, когда я получаю упомянутую ошибку Ansible о неудачном удалении контейнера, команда CLI вручную
docker rm
также завершается с той же ошибкой. Я используюDocker 1.12.1
, я должен уничтожить компьютер и заново создать его снова, чтобы снова развернуть3. Попробуйте lsof, чтобы узнать, можете ли вы отследить, что блокирует доступ к каталогам / файлам docker.
4. @BMitch Я проверил, что на самом деле так и было
v1.12.0
, также проверил репозиторий Docker GitHub и увидел, что их последний список изменений дляv1.12.2
включает » Реализовать логику повторных попыток для предотвращения ошибок «Невозможно удалить файловую систему» при использовании драйвера хранилища aufs «, ссылаясь на этот PR . Я проверю, сохраняется ли проблема в этой версии, и, если возможно, также проверю сlsof
помощью команды5. @BMitch к сожалению, проблема, похоже, сохраняется в
1.12.2
версии: (вывод lsof немного чудовищный, 4K строк и 650 строкgrep docker
, я загрузил оба в СУТЬ , но я не вижу там ни одной строки, которая выглядела бы как смонтированный докером том, только много строк, ссылающихся на/var/lib/docker/volumes/metadata.db
Ответ №1:
Я сам публикую ответ, надеюсь, это поможет кому-нибудь справиться с той же проблемой, с которой я столкнулся с Docker.
Я следовал этому руководству, которое в основном состоит в добавлении параметра в модульный файл docker systemd. Я добавил MountFlags=private
строку в [service]
раздел. Похоже, что проблема связана с пространствами имен файловой системы. С помощью этого исправления я могу развертывать контейнеры с любого количества хостов, которые я хочу, и есть 0 ошибок.
Комментарии:
1. Эта проблема сводила меня с ума в течение нескольких дней. Но я не сталкивался с ошибкой уже через день после добавления
MountFlags=private
. Я просто не могу в это поверить! Спасибо, что вы один из тех парней, которые сами отвечают на свой вопрос 🙂