uwsgi && docker
Замечательный софт, без сомнения.
Проблемы запуска uwsgi в docker ровно две - и обе они кроются в init скриптах автора.
1) /etc/init.d/uwsgi start вываливается с ошибкой. вот просто так, из коробки, сразу. Погружаемся в исходники и начинаем искать проблему. Она кроется в выполнении этой команды:
До этого этапа все выполняется прекрасно, процессы стартуют и главное начинают работать даже после выпадения с ошибкой init-скрипта. Проблема кроется в том, что внутри докера нет прав на прочтение /proc/{id}/exe. После чего считается что процесса нет и согласно заложенному поведению выдается код возврата 0, отсюда выдается код возврата 2 (return 2), который и дает в результате ошибку запуска. Обсуждение этого косяка при запуске разного ПО идет аж с 14 года: https://github.com/moby/moby/issues/6800.
Workaround:
a) исправляем в файле /usr/share/uwsgi/init/specific_daemon в приведенном мною выше коде ключ --exec на --startas. Согласно ману (да нет, шутка, согласно ману они одинаково работают, так что согласно форумам) при использовании ключа startas будет пропущена проверка /proc/{id}/exe и просто проверяется запущен ли процесс с таким pid. (https://chris-lamb.co.uk/posts/start-stop-daemon-exec-vs-startas)
b) запуск контейнера с ключем --cap-add=SYS_PTRACE. В этом случае править ничего не нужно.
с) не использовать авторские init-скрипты и запускать напрямую
2) После запуска /etc/init.d/uwsgi start скрипт прекрасно отрабатывает и выходит. Докер естественно после этого завершается. Причем демонизация захардкожена автором в скрипте запуска, без возможности указать в конфиге хочешь ты этого или нет. На этом моменте я все же психанул и сначала поправил скрипт запуска, но потом понял что все же это не тру путь и нужно от этого отказываться, делая просто одну строчку запуска и один конфиг файл.
В итоге что было сделано:
1) в конфиг добавлены следующие параметры (и остальные из дефолтного конфига):
2) в Dockerfile:
таким образом мы избавились и от той левой проверки из п.1 и от ключа демонизации из п.2, и сами выставили права и место pid\socket.
#troubleshooting #docker #uwsgi
Замечательный софт, без сомнения.
Проблемы запуска uwsgi в docker ровно две - и обе они кроются в init скриптах автора.
1) /etc/init.d/uwsgi start вываливается с ошибкой. вот просто так, из коробки, сразу. Погружаемся в исходники и начинаем искать проблему. Она кроется в выполнении этой команды:
start-stop-daemon --start --quiet \
--pidfile "$PIDFILE" \
--exec "$DAEMON" \
--test > /dev/null \
&& return 2
До этого этапа все выполняется прекрасно, процессы стартуют и главное начинают работать даже после выпадения с ошибкой init-скрипта. Проблема кроется в том, что внутри докера нет прав на прочтение /proc/{id}/exe. После чего считается что процесса нет и согласно заложенному поведению выдается код возврата 0, отсюда выдается код возврата 2 (return 2), который и дает в результате ошибку запуска. Обсуждение этого косяка при запуске разного ПО идет аж с 14 года: https://github.com/moby/moby/issues/6800.
Workaround:
a) исправляем в файле /usr/share/uwsgi/init/specific_daemon в приведенном мною выше коде ключ --exec на --startas. Согласно ману (да нет, шутка, согласно ману они одинаково работают, так что согласно форумам) при использовании ключа startas будет пропущена проверка /proc/{id}/exe и просто проверяется запущен ли процесс с таким pid. (https://chris-lamb.co.uk/posts/start-stop-daemon-exec-vs-startas)
b) запуск контейнера с ключем --cap-add=SYS_PTRACE. В этом случае править ничего не нужно.
с) не использовать авторские init-скрипты и запускать напрямую
2) После запуска /etc/init.d/uwsgi start скрипт прекрасно отрабатывает и выходит. Докер естественно после этого завершается. Причем демонизация захардкожена автором в скрипте запуска, без возможности указать в конфиге хочешь ты этого или нет. На этом моменте я все же психанул и сначала поправил скрипт запуска, но потом понял что все же это не тру путь и нужно от этого отказываться, делая просто одну строчку запуска и один конфиг файл.
В итоге что было сделано:
1) в конфиг добавлены следующие параметры (и остальные из дефолтного конфига):
...
stats = 0.0.0.0:9090
socket = 0.0.0.0:3031
pidfile = /run/uwsgi/pid
socket = /run/uwsgi/socket
...
2) в Dockerfile:
...
COPY app.ini /etc/uwsgi/apps-enabled/app.ini
RUN mkdir /run/uwsgi && chown www-data /run/uwsgi
CMD ["/usr/bin/uwsgi", "--ini", "/etc/uwsgi/apps-enabled/app.ini"]
таким образом мы избавились и от той левой проверки из п.1 и от ключа демонизации из п.2, и сами выставили права и место pid\socket.
#troubleshooting #docker #uwsgi
Используем systemd для запуска docker-контейнеров
#systemd #docker
[Unit]
Description=My Awesome Service
Requires=docker.service
After=docker.service
[Service]
Restart=always
RestartSec=3
ExecStartPre=/bin/sh -c "/usr/bin/docker rm -f my-awesome-service 2> /dev/null || /bin/true"
ExecStart=/usr/bin/docker run --rm -a STDIN -a STDOUT -a STDERR --env-file=/etc/default/my-awesome-service -p 0.0.0.0:3301:3301 -v /etc/project/service:/etc/wallarm -v /var/lib/blacklist:/var/lib/blacklist -v /var/log/project/service:/var/log/wallarm --name my-awesome-service wallarm-dkr.jfrog.io/my-awesome-service:v0.17.0.0
ExecStop=/usr/bin/docker stop my-awesome-service
[Install]
WantedBy=multi-user.target
#systemd #docker
Билдим собственный однобинарный образ на примере hello-world
все примеры взяты с гитхабчика докера и изменены в пользу упрощения.
Для задачи будет использоваться слой scratch, который представляет из себя слой без какой-либо начинки. Использование образа scratch сигнализирует билд-процессу, что следующая команда в Dockerfile будет вашим первым слоем в образе. Таким образом мы получаем контейнер, состоящий как бы из одного вашего бинаря.
Все что нам нужно - запуск одного бинарника, поэтому при использовании scratch итоговый образ получается легким как перышко.
1) Возьмем С-код, которые выведет на экран слова приветствия
2) сбилдим:
3) Dockerfile:
4) билдим образ:
5) проверяем:
и ответ:
Сравнение
если запросить
Благодарности Михаилу за помощь с Си =)
#docker #hello_world
все примеры взяты с гитхабчика докера и изменены в пользу упрощения.
Для задачи будет использоваться слой scratch, который представляет из себя слой без какой-либо начинки. Использование образа scratch сигнализирует билд-процессу, что следующая команда в Dockerfile будет вашим первым слоем в образе. Таким образом мы получаем контейнер, состоящий как бы из одного вашего бинаря.
Все что нам нужно - запуск одного бинарника, поэтому при использовании scratch итоговый образ получается легким как перышко.
1) Возьмем С-код, которые выведет на экран слова приветствия
#include <unistd.h>
#include <sys/syscall.h>
const char message[] =
"\n"
"hello world\n"
"\n";
void main() {
//write(1, message, sizeof(message) - 1);
syscall(SYS_write, 1, message, sizeof(message) - 1);
//_exit(0);
syscall(SYS_exit, 0);
}
2) сбилдим:
gcc hello.c -o hello -static
3) Dockerfile:
FROM scratch
COPY hello /
CMD ["/hello"]
4) билдим образ:
docker build -t hello ./
5) проверяем:
docker run hello
и ответ:
hello world
Сравнение
если запросить
du -hs hello
и посмотреть docker images hello
их разница будет всего в пару десятков КБ. (792K -> 810К в моем случае)Благодарности Михаилу за помощь с Си =)
#docker #hello_world
Список тегов, используемых в канале:
—-------------------------------
Лекции и материалы
—-------------------------------
#Занятие
#Лекции
Лекция
#junior
—---------
Linux
—---------
#ssh
#bash
#bash_tips_and_tricks
#awk
#tmux
#console
#utils
#troubleshooting
#nmap
#apt
#bind
#sound
#power_management
—----------
DevOps
—----------
#jenkins
#ansible
#git
#kubernetes
#deploy
#ceph
#docker
#puppet
—------------------
Virtualization
—------------------
#vmware
vagrant
—------------------
Networking
—---------------—
#networking
#proxy
#socks
—---------
InfoSec
—---------
#vulns
#security
#ctf
—-------------
Windows
—-------------
#RDTS
#windows_server2012
#RDP
—------------
Datacenters
—---------—
#ovh
#hetzner
—-------
Other
—-------
#android
#jira
—------------------------------------------------
Ссылки и сторонние материалы
—------------------------------------------------
#read
#thirdparty
Updated: 29.05.18
—-------------------------------
Лекции и материалы
—-------------------------------
#Занятие
#Лекции
Лекция
#junior
—---------
Linux
—---------
#ssh
#bash
#bash_tips_and_tricks
#awk
#tmux
#console
#utils
#troubleshooting
#nmap
#apt
#bind
#sound
#power_management
—----------
DevOps
—----------
#jenkins
#ansible
#git
#kubernetes
#deploy
#ceph
#docker
#puppet
—------------------
Virtualization
—------------------
#vmware
vagrant
—------------------
Networking
—---------------—
#networking
#proxy
#socks
—---------
InfoSec
—---------
#vulns
#security
#ctf
—-------------
Windows
—-------------
#RDTS
#windows_server2012
#RDP
—------------
Datacenters
—---------—
#ovh
#hetzner
—-------
Other
—-------
#android
#jira
—------------------------------------------------
Ссылки и сторонние материалы
—------------------------------------------------
#read
#thirdparty
Updated: 29.05.18
Docker up to date checking
Сервис для проверки ваших докер контейнеров на "обновленность". Для публичных - бесплатно. приватные - за денежку.
https://anchore.io/
#docker
Сервис для проверки ваших докер контейнеров на "обновленность". Для публичных - бесплатно. приватные - за денежку.
https://anchore.io/
#docker
Anchore
Software supply chain security solutions • Anchore
Protect your software supply chain with policy-based container security solutions.
Убитый контейнер докера не запускается
Ошибка:
#docker #troubleshooting #networking
Ошибка:
endpoint with name XXXX already exists in network bridge.
Решение:docker network disconnect --force bridge <Container ID or Endpoint ID or Container NAME>
Это не для тех, кто не умеет гуглить, а для того чтобы наоборот каждый раз не гуглить когда такое возникает=)#docker #troubleshooting #networking
Запускаем задачу в background в докер контейнере через ansible
Особо ничего сложного, nohup да &, однако процесс все равно не отпускает консоль, посему ansible зависает. Чтобы этого не происходило, можно применить такую конструкцию:
Особо ничего сложного, nohup да &, однако процесс все равно не отпускает консоль, посему ansible зависает. Чтобы этого не происходило, можно применить такую конструкцию:
- name: run bg job#docker #ansible
shell: docker exec -i <container> sh -c 'nohup CMD &'
async: 45
poll: 0
RBAC on docker registry
Поигрался тут на днях с одним сервисом который позволяет использвать token-based аутентификацию пользователя с docker registry. Стандартный вариант логин-пароль уже не удовлетворяет потребностям и пришлось искать что-то другое. В итоге набрел на готовое решение от cesanta/docker_auth. Написано на go, легковестный token-сервис с поддержкой различных способов аутентификации пользователей и также, что самое главное - это ACL. С помощью acl можно задавать кто, и какие репозитории может пушить и пуллить, с точностью до регулярного выражения. В качестве базы хранения пользователей-acl можно выбрать статический файл, mongodb, ldap и некоторые другие. В том числе можно использовать и сторонний софт, хоть самопис. токен будет выдаваться в зависимости от кода ответа этого софта. И тут уже можно сделать все что угодно - хоть выдавать токены в зависимости от времени суток. Поковырявшись в этом собрал готовое решение, запускаемое через docker-compose. Оно содержит набор из 3 контейнеров: docker_auth, docker registry и mongo. После старта docker-compose все что нужно сделать - загрузить список правил и пользователей в mongo через простейший shell-скрипт.
https://github.com/bykvaadm/docker_auth
#docker #auth
Поигрался тут на днях с одним сервисом который позволяет использвать token-based аутентификацию пользователя с docker registry. Стандартный вариант логин-пароль уже не удовлетворяет потребностям и пришлось искать что-то другое. В итоге набрел на готовое решение от cesanta/docker_auth. Написано на go, легковестный token-сервис с поддержкой различных способов аутентификации пользователей и также, что самое главное - это ACL. С помощью acl можно задавать кто, и какие репозитории может пушить и пуллить, с точностью до регулярного выражения. В качестве базы хранения пользователей-acl можно выбрать статический файл, mongodb, ldap и некоторые другие. В том числе можно использовать и сторонний софт, хоть самопис. токен будет выдаваться в зависимости от кода ответа этого софта. И тут уже можно сделать все что угодно - хоть выдавать токены в зависимости от времени суток. Поковырявшись в этом собрал готовое решение, запускаемое через docker-compose. Оно содержит набор из 3 контейнеров: docker_auth, docker registry и mongo. После старта docker-compose все что нужно сделать - загрузить список правил и пользователей в mongo через простейший shell-скрипт.
https://github.com/bykvaadm/docker_auth
#docker #auth
GitHub
bykvaadm/docker_auth
example of cesanta/docker_auth. Contribute to bykvaadm/docker_auth development by creating an account on GitHub.
Cleanup docker registry
Проверено для версии 2.6.2
1. добавить в конфиг registry эти строки и перезапустить:
2. получаем список тегов для репозитория и выбираем список на удаление
3. помечаем объекты на удаление через api
4. заходим внутрь контейнера и запускаем garbage-collector.
Итого наша задача - получить список тегов, выбрать нужные на удаление. На каждый тег получить sha256 манифеста (docker-content-digest в заголовке ответа), а затем пометить этот заголовок на удаление. К концу 3-го пункта никакие данные еще не удалены. Удаление происходит не вручную, а с помощью нативного сборщика мусора. согласно помеченным манифестам будут удалены выбранные теги.
#docker #registry
Проверено для версии 2.6.2
1. добавить в конфиг registry эти строки и перезапустить:
storage:
delete:
enabled: true
2. получаем список тегов для репозитория и выбираем список на удаление
curl -u <user>:<password> https://<registry_host>/v2/<repo_name>/tags/list
3. помечаем объекты на удаление через api
repo="REPO_PATH"
tag_list='TAG LIST separated by space'
user="USER"
pwd="PASSWORD"
registry_host="<registry_host>"
header="Accept: application/vnd.docker.distribution.manifest.v2+json"
for tag in ${tag_list}; do
digest=$(curl -I -u $user:$pwd -H "$header" "https://${registry_host}/v2/${repo}/manifests/${tag}" 2>/dev/null| awk '$1 == "docker-content-digest:" {print $2}'| tr -dc '[[:print:]]')
curl -XDELETE -u $user:$pwd -H "$header" "https://${registry_host}/v2/${repo}/manifests/${digest}"
done
4. заходим внутрь контейнера и запускаем garbage-collector.
registry garbage-collect /etc/docker/registry/config.yml
Итого наша задача - получить список тегов, выбрать нужные на удаление. На каждый тег получить sha256 манифеста (docker-content-digest в заголовке ответа), а затем пометить этот заголовок на удаление. К концу 3-го пункта никакие данные еще не удалены. Удаление происходит не вручную, а с помощью нативного сборщика мусора. согласно помеченным манифестам будут удалены выбранные теги.
#docker #registry
Интегрируем проверку на уязвимости в CI
The Anchore Engine is an open source project that provides a centralized service for inspection, analysis and certification of container images.
https://github.com/anchore/anchore-engine
https://medium.com/devopslinks/step-by-step-guide-to-integrate-opensource-container-security-scanner-anchore-engine-with-cicd-580da8db5dfc
#docker #jenkins #security
The Anchore Engine is an open source project that provides a centralized service for inspection, analysis and certification of container images.
https://github.com/anchore/anchore-engine
https://medium.com/devopslinks/step-by-step-guide-to-integrate-opensource-container-security-scanner-anchore-engine-with-cicd-580da8db5dfc
#docker #jenkins #security
Нападение без объявления войны
я хз че это было, но вы поймете когда вам это понадобится))
https://github.com/moby/moby/blob/master/contrib/init/systemd/docker.socket
(Ну а так, ошибка такая: docker.service: Failed to schedule restart job: Unit docker.socket not found.)
#docker #troubleshooting
я хз че это было, но вы поймете когда вам это понадобится))
https://github.com/moby/moby/blob/master/contrib/init/systemd/docker.socket
(Ну а так, ошибка такая: docker.service: Failed to schedule restart job: Unit docker.socket not found.)
#docker #troubleshooting
GitHub
moby/contrib/init/systemd/docker.socket at master · moby/moby
The Moby Project - a collaborative project for the container ecosystem to assemble container-based systems - moby/moby
куда можно потратить 3 часа
Способов потерять время - сотни. Можно поваляться на траве в погожий денек, написать какой-нибудь прикольной зеленоглазой девчонке, а можно... собирать пакеты и тестировать их в докере. И убить эти 3 часа в попытке исполнить .examples/.docs скрипты установки. Ну это те, которые приносят файлики в /usr/share/docs/<package>. Вы кладете туда файл, а он не приезжает после установки пакета. Самое главное что если пакет вскрыть с помощью ar, то нужные файлы там есть. При установке пакета - в нужных местах не появляются. Самое бесячее, что в нужной папке появляется файл copyright, а твои другие - нет.
Ларчик-то просто открывался. Всего-навсего в докере из коробки лежит конфиг dpkg, который говорит, мол copyright клади, а другие файлы не клади...
#packaging #docker
Способов потерять время - сотни. Можно поваляться на траве в погожий денек, написать какой-нибудь прикольной зеленоглазой девчонке, а можно... собирать пакеты и тестировать их в докере. И убить эти 3 часа в попытке исполнить .examples/.docs скрипты установки. Ну это те, которые приносят файлики в /usr/share/docs/<package>. Вы кладете туда файл, а он не приезжает после установки пакета. Самое главное что если пакет вскрыть с помощью ar, то нужные файлы там есть. При установке пакета - в нужных местах не появляются. Самое бесячее, что в нужной папке появляется файл copyright, а твои другие - нет.
Ларчик-то просто открывался. Всего-навсего в докере из коробки лежит конфиг dpkg, который говорит, мол copyright клади, а другие файлы не клади...
#packaging #docker
Интересное наблюдение
На одном из серверов выполнил вот такую команду:
Вы наверное тоже насторожились как и я, какого хрена nginx запущен от папета. Оказалось все довольно просто. На сервере nginx запущен в докере:
А вот ответ на вопрос как так получилось:
#docker
На одном из серверов выполнил вот такую команду:
# ps aux | grep nginx
puppet 6754 ... nginx: worker process
puppet 6755 ... nginx: worker process
Вы наверное тоже насторожились как и я, какого хрена nginx запущен от папета. Оказалось все довольно просто. На сервере nginx запущен в докере:
# docker exec -ti 4da030b0cfb5 ps aux | grep nginx
nginx 668 nginx: worker process
nginx 669 nginx: worker process
А вот ответ на вопрос как так получилось:
# grep puppet /etc/passwd
puppet:x:105:109:Puppet configuration ....
# docker exec -ti 4da030b0cfb5 grep nginx /etc/passwd
nginx:x:105:111:nginx user
#docker
terraform create dockreg secret in k8s
resource "kubernetes_secret" "company-dkr-key" {#terraform #docker #kubernetes
metadata {
name = "company-dkr-key"
namespace = "${kubernetes_namespace.company.metadata.0.name}"
}
data = {
".dockerconfigjson" = "{\"auths\":{\"${var.company-dkr-url}\":{\"username\":\"${var.company-dkr-user}\",\"password\":\"${var.company-dkr-password}\",\"email\":\"email\",\"auth\":\"${base64encode(format("%s:%s", var.company-dkr-user, var.company-dkr-password))}\"}}}"
## OR u can also do this from file
# ".dockercfg" = "${file("${path.module}/docker.cfg")}"
}
type = "kubernetes.io/dockercfg"
}
как сбросить пароль на postgresql в запущенном docker контейнере без перезапуска
Рубрика "костылим с буквой"
ОСТОРОЖНО прочитанное далее может вызвать кровотечение из глаз и непреодолимое желание расшибить себе лоб рукой.
вы были предупреждены.
Раскатывал я тут хелм сентри... Дано: не работающий Job, который использует пароль из секрета, и криво написанный авторами чарт, в котором слетает пароль пользователя в postgres. Задача - установить в контенере на лету нужный пароль пользователя.
#рукиизжопы #костыли #postgresql #docker #sentry #kubernetes
Рубрика "костылим с буквой"
ОСТОРОЖНО прочитанное далее может вызвать кровотечение из глаз и непреодолимое желание расшибить себе лоб рукой.
вы были предупреждены.
Раскатывал я тут хелм сентри... Дано: не работающий Job, который использует пароль из секрета, и криво написанный авторами чарт, в котором слетает пароль пользователя в postgres. Задача - установить в контенере на лету нужный пароль пользователя.
# получаем пароль который должен быть выставлен на постгре
kubectl -n sentry get secret sentry-sentry-postgresql -o yaml | awk '$1=/postgresql-password:/ {print $2}' | base64 -d; echo
# получаем ноду на которой крутится постгре и ssh-шимся на нее
kubectl -n sentry get po -o wide | awk '$1~/.*postgr.*/ {print $7}'
# получаем id контейнера и логинимся туда под рутом
docker ps | grep postgr | grep entry | awk '{print $1}'
docker exec -ti -u0 <container_id> bash
# узнаем пользователя под которым запущен постгре
grep Uid /proc/1/task/1/status
# разрешаем логиниться из-под локалхоста
sed -ibak 's/^\([^#]*\)md5/\1trust/g' /opt/bitnami/postgresql/conf/
# добавляем пользователя в систему и переходим в него
useradd postgres -u 1001
su postgres
# выставляем переменные окружения и релоадим сервис
export PGDATA=/bitnami/postgresql/data
/opt/bitnami/postgresql/bin/pg_ctl reload
# логинимся в postgres и выставляем пароль
psql -U postgres
ALTER USER postgres WITH PASSWORD 'XXX';
возвращаем назад изменения или перестартуем контейнер.
#рукиизжопы #костыли #postgresql #docker #sentry #kubernetes
Happy New Year! With a new year upon us, it's time to reflect on the best Docker content and projects from 2019 sourced from our Docker experts and our exceptional Docker community and community leaders. Check out our most binge-worthy content of 2019 as you begin to map your Docker journey for 2020.
Top 5 Docker Blogs from 2019
Intro Guide to Dockerfile Best Practices by Tibor Vass - July 2, 2019
Happy Pi Day with Docker and Raspberry Pi by Paulo Frazao - March 14, 2019
5 Things to Try with Docker Desktop WSL 2 Tech Preview by Ben De St Paer-Gotch - July 31, 2019
New in Docker Hub: Personal Access Token by Shenea Leven - September 19, 2019
Docker's Next Chapter: Advancing Developer Workflows for Modern Apps by Scott Johnston - November 13, 2019
Top Docker & Docker Captain Projects:
Container registry with commands in an Alpine image
Golang library with API to run Docker container
docker-compose stack for Prometheus monitoring
Sample node app for Docker examples
#docker #подборка
Top 5 Docker Blogs from 2019
Intro Guide to Dockerfile Best Practices by Tibor Vass - July 2, 2019
Happy Pi Day with Docker and Raspberry Pi by Paulo Frazao - March 14, 2019
5 Things to Try with Docker Desktop WSL 2 Tech Preview by Ben De St Paer-Gotch - July 31, 2019
New in Docker Hub: Personal Access Token by Shenea Leven - September 19, 2019
Docker's Next Chapter: Advancing Developer Workflows for Modern Apps by Scott Johnston - November 13, 2019
Top Docker & Docker Captain Projects:
Container registry with commands in an Alpine image
Golang library with API to run Docker container
docker-compose stack for Prometheus monitoring
Sample node app for Docker examples
#docker #подборка