определить дистрибутив ОС образа докера

Мне нужно определить имя дистрибутива ОС для любого образа докера. Я могу пометить ubuntu:latest как image1:latest, но я должен получить информацию о распространении image1:latest при его запуске.

Для этого я использовал приведенную ниже команду для определения версии ОС:

$ docker tag ubuntu image1
$
$ docker run -it image1 /bin/sh -c "echo import platform > test.py; echo print\(platform.dist\(\)\) >> test.py; python3 test.py"
('Ubuntu', '14.04', 'trusty')
$

Однако это зависит от того, содержит ли изображение python2 или python3. Это не работает для Ubuntu: 12.04, и мне нужно использовать там python2.

$ docker run -it ubuntu /bin/sh -c "echo import platform > test.py; echo print\(platform.dist\(\)\) >> test.py; python3 test.py"
('Ubuntu', '14.04', 'trusty')
$
$ docker run -it ubuntu:12.04 /bin/sh -c "echo import platform > test.py; echo print\(platform.dist\(\)\) >> test.py; python3 test.py"
/bin/sh: 1: python3: not found
$
$ docker run -it ubuntu:12.04 /bin/sh -c "echo import platform > test.py; echo print\(platform.dist\(\)\) >> test.py; python2 test.py"
('Ubuntu', '12.04', 'precise')
$ 

Q1. Есть ли способ добиться того же, не зная, какая версия python находится в конкретном изображении?

ПРИМЕЧАНИЕ. Цель состоит в том, чтобы определить, какой базовый образ использовался для создания этого образа. У меня нет доступа к файлу Dockerfile, который использовался для создания этого образа.

Q2. Существует еще один подход к использованию точки входа. Я могу создать отдельный образ из текущего образа, используя Dockerfile. Или я могу указать точку входа в командной строке при создании контейнера, но мне нужно, чтобы скрипт был доступен внутри контейнера. Я предполагаю, что мне может понадобиться общее хранилище при использовании cmdline, есть ли лучший способ добиться этого? Любые указатели были бы действительно полезны.

Спасибо.


person Rahul    schedule 28.02.2016    source источник
comment
uname -a дает мне это: Linux 95e5ae04dbbc 4.2.0-27-generic #32-Ubuntu SMP Пт, 22 января, 04:49:08 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux. Я не могу сказать, Ubuntu14.04, Fedora или Ubuntu15.10.   -  person Rahul    schedule 29.02.2016
comment
Даже для использования sys мне нужно знать, какую версию python использовать. Сам вопрос в том, как я могу определить, какую версию использовать. :)   -  person Rahul    schedule 29.02.2016
comment
Я продолжал читать ваш вопрос неправильно. Именно поэтому я удалил свои комментарии. Извинения. :)   -  person idjaw    schedule 29.02.2016


Ответы (5)


Стандарт иерархии файловой системы имеет стандартное определение для /etc/os-release, которое должно быть доступным в большинстве дистрибутивов:

Файлы /etc/os-release и /usr/lib/os-release содержат идентификационные данные операционной системы.

Базовый формат файла os-release представляет собой разделенный новой строкой список назначений переменных, совместимых с оболочкой, подобных среде. Конфигурацию можно получить из сценариев оболочки.

Это означает, что вы можете просто получить /etc/os-release и использовать $NAME или $ID для идентификации дистрибутива. Например, в Fedora это выглядит так:

% source /etc/os-release
% echo $NAME
Fedora
% echo $ID
fedora

В Дебиане:

% source /etc/os-release
% echo $NAME
Debian GNU/Linux
% echo $ID
debian
person morxa    schedule 29.02.2016
comment
Это выглядит хорошо. Работает на последних дистрибутивах. Однако, когда я попытался увидеть изображение centos: 6, в нем нет этого файла. centos: у последнего есть. - person Rahul; 29.02.2016
comment
RHEL6 (и, следовательно, CentOS 6) настолько стар, что тогда /etc/os-release еще не существовало. Вместо этого вы можете использовать glob для /etc/*-release. Я думаю, что у RHEL6 был /etc/redhat-release, я думаю, что у CentOS есть что-то подобное. - person morxa; 29.02.2016
comment
Спасибо @morxa. Я использовал комбинацию python и os-release для получения информации о версии. На данный момент он охватывает почти все случаи (redhat, ubuntu, debian, centos, opensuse, cirros...) github.com/BU-NU-CLOUD-SP16/Container-Code-Classification/blob/ - person Rahul; 01.03.2016

Вы можете использовать файл /etc/issue для Debian/Ubuntu:

root@ubuntu_container:/# cat /etc/issue
Ubuntu 14.04.3 LTS \n \l

или /etc/redhat-release для CentOS/Red Hat/Fedora:

[root@fedora_container /]# cat /etc/redhat-release 
Fedora release 23 (Twenty Three)

[root@centos_container /]# cat /etc/redhat-release 
CentOS Linux release 7.2.1511 (Core)
person pie    schedule 28.02.2016
comment
Не подходит для Centos. `sh-4.2# cat /etc/issue -----› дает ----› Ядро \r на \m` - person Rahul; 29.02.2016
comment
для каждого дистрибутива команда будет меняться. Например, он изменился с Ubuntu на Redhat. Точно так же это может измениться для openuse. Это решение, похоже, не масштабируется. - person Rahul; 29.02.2016

Большинство ответов дают нам версию ОС, но вопрос также касается докера.

Я ленив, особенно когда у меня более 20 изображений, поэтому:

docker image ls | perl -lane 'print "docker run --rm $F[0]:$F[1] cat /etc/os-release" unless /REPOSITORY/' | sh | grep PRETTY

И большинство изображений имеют результаты:

> PRETTY_NAME="Ubuntu 16.04.1 LTS"
> PRETTY_NAME="Ubuntu 14.04.3 LTS"
> PRETTY_NAME="Ubuntu 18.04.1 LTS"
> PRETTY_NAME="Debian GNU/Linux 9 (stretch)" 
> PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
> PRETTY_NAME="Debian GNU/Linux bullseye/sid"
> PRETTY_NAME="Ubuntu 18.04.3 LTS"
> PRETTY_NAME="Ubuntu 16.04.1 LTS"
> ...
person Qinsi    schedule 06.08.2020

Вы должны использовать следующую команду для определения имени выпуска Ubuntu:

export UBUNTU_RELEASE=$(lsb_release  -sc || cat /etc/*-release|grep -oP  'CODENAME=\K\w+$'|head -1)

Для изображений докеров Ubuntu я использую следующие cmds, когда мне нужно добавить мультивселенную в apt.source.lists и не иметь повторяющихся строк:

RUN export UBUNTU_RELEASE=$(lsb_release  -sc || cat /etc/*-release|grep -oP  'CODENAME=\K\w+$'|head -1) &&\
    echo "deb http://archive.ubuntu.com/ubuntu/ ${UBUNTU_RELEASE}-security multiverse" >> /etc/apt/sources.list && \
    echo "deb-src http://archive.ubuntu.com/ubuntu/ ${UBUNTU_RELEASE}-security multiverse" >> /etc/apt/sources.list && \
    echo "deb http://archive.ubuntu.com/ubuntu/ ${UBUNTU_RELEASE} multiverse" >> /etc/apt/sources.list && \
    echo "deb-src http://archive.ubuntu.com/ubuntu/ ${UBUNTU_RELEASE} multiverse" >> /etc/apt/sources.list && \
    echo "removing duplicated strings from /etc/apt/sources.list" && \
    awk '!x[$0]++' /etc/apt/sources.list > /tmp/sources.list && \
    cat /tmp/sources.list > /etc/apt/sources.list && \

Вы должны использовать следующую команду для определения имени выпуска Debian ( Я использую его для своих образов докеров):

export DEBIAN_RELEASE=$(awk -F'[" ]' '/VERSION=/{print $3}'  /etc/os-release | tr -cd '[[:alnum:]]._-' ) && \
     [[ "x${DEBIAN_RELEASE}" = "x" ]] && export DEBIAN_RELEASE="unstable" 
person Valeriy Solovyov    schedule 03.05.2016
comment
Согласен, но это работает только для Ubuntu. Вопрос в том, как определить для большинства операционных систем. Выбранный ответ и комментарии к нему хорошо подходят для большинства важных дистрибутивов. А еще проще. - person Rahul; 03.05.2016
comment
Python не является частью дистрибутива некоторых базовых образов Docker. Поэтому я предлагаю встроить определенные обнаружения в зависимости от типа вашего дистрибутива. PS: я добавил Debian и обновлю в следующих дистрибутивах. - person Valeriy Solovyov; 04.05.2016
comment
Да, именно поэтому я сначала использовал /etc/os-release, а если его нет, то полагаюсь на python. Вы можете проверить комментарий в ответе, который указывает на ссылку github, делающую то же самое. Да, это не работает для образов, в которых нет ни /etc/os-release, ни python, но в остальном это работает для многих известных дистрибутивов. - person Rahul; 04.05.2016

Расширяя ответ и комментарий @morxa, некоторые sh не имеют source определенных. В таком случае мы можем использовать

grep NAME /etc/*-release

чтобы увидеть, что такое ОС. Обычно PRETTY_NAME может сказать полное имя:

PRETTY_NAME="Ubuntu 20.04 LTS"
person nonopolarity    schedule 12.05.2020