#docker #ipc #shared-memory
#docker #ipc #разделяемая память
Вопрос:
Я пытаюсь настроить общую память на своем главном компьютере и получить к ней доступ в centos:7
контейнере docker с shmat
помощью функции. Я создал общую память, используя ipcmk -M 1024
и написал программу на C с жестко заданным идентификатором (для целей отладки):
// shmtest.c
const char* shm_id = "98321";
shared_memory = shmat(atoi(shm_id), NULL, 0);
if (shared_memory == (void*)-1) {
perror("No shared memory area");
abort();
}
fprintf(stdout, "Shared memory found!n");
Мой Dockerfile очень прост, все, что я делаю, это копирую скомпилированную программу и сохраняю контейнер в рабочем состоянии, чтобы я мог проверять его с помощью интерактивной оболочки:
# Dockerfile
FROM centos:7
COPY ./shmtest /root/
CMD tail -f /dev/null
Я создаю и запускаю контейнер с помощью
docker build -t shm-docker .
docker run --ipc="host" shm-docker
Внутри контейнера docker я запускаю свою shmtest
программу, но не могу получить доступ к общей памяти:
./shmtest
No shared memory area: Permission denied
Aborted
Однако ipcs
отображается общая память:
ipcs -m | grep 98321
0x8a39b8b3 98321 1000 644 65536 0
Я пробовал:
- Запуск контейнера docker с
-v /dev/:/dev/
помощью и-v /dev/shm/:/dev/shm/
, без какой-либо удачи - Предоставление моей программе возможности CAP_IPC_OWNER и CAP_IPC_LOCK с
setcap
помощью; тогда я не смог его запустить (./shmtest: Operation not permitted
) - Переключение
centos:7
в моем Dockerfile сubuntu:18.04
помощью , по-прежнему не сработало, что означает, что эта проблема не характерна для centos
К сожалению, я мало что знаю о разрешениях, но я заметил, что моя общая память показывает номер 644
при запуске ipcs
, а также различные другие 600
. Я также пытался получить к ним доступ, и я все еще получаю ту же ошибку.
Чего мне здесь не хватает? Действительно ли моя идея верна или невозможно получить доступ к общей памяти таким образом?
Ответ №1:
Разрешения 644
общей памяти позволяют ее владельцу читать и записывать (первые 6), но предоставляют доступ на чтение только всем остальным (последние 4).
root
Пользователь в контейнере docker не является владельцем общей памяти, поэтому у него нет разрешения на запись в общую память.
Если у вас есть доступ к инструменту, который создает общую память, вы можете изменить разрешения на что-то вроде 606
, что означает доступ на чтение и запись для владельца и всех остальных тоже. Например, у ipcmk
команды есть -p
опция, поэтому вы должны выполнить ipcmk -M 1024 -p 0606
.
Если вы не можете изменить способ создания общей памяти, это можно решить, добавив --privileged
флаг или, точнее, --cap-add=IPC_OWNER
флаг в docker run
команду. Из ссылки на запуск docker:
Когда оператор выполняет docker run —privileged, Docker разрешает доступ ко всем устройствам на хосте, а также задает некоторую конфигурацию в AppArmor или SELinux, чтобы предоставить контейнеру почти тот же доступ к хосту, что и процессам, запущенным вне контейнеров на хосте.
В дополнение к —privileged оператор может иметь точный контроль над возможностями, используя —cap-add и —cap-drop .
И что касается IPC_OWNER
возможности:
IPC_OWNER — обход проверок разрешений для операций с объектами System V IPC.
Полная команда теперь либо
docker run --ipc="host" --privileged shm-docker
или
docker run --ipc="host" --cap-add=IPC_OWNER shm-docker
Хорошим инструментом для понимания разрешений является калькулятор Chmod, который представляет собой интерактивный инструмент, позволяющий увидеть, как разрешения кодируются восьмеричными цифрами и символами.