determine OS distribution of a docker image

Question:

I need to determine the OS distribution name for any docker image. I can tag ubuntu:latest as image1:latest, but I should be able to get the distribution information of image1:latest when it is launched.

For achieving this, I used the below mentioned command to determine the OS version:

$ 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')
$

However, this has a dependency on whether the image has python2 or python3 in it. It fails for ubuntu:12.04 and I need to use python2 there.

$ 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. Is there a way I can achieve the same without knowing which version of python is there in a particular image?

NOTE: The goal is to determine which was the base image used to build this image. I don’t have access to the Dockerfile used to build this image.

Q2. There is another approach of using entrypoint. I can build a separate image from the current image using Dockerfile. Or, I can specify entrypoint in cmdline when creating container but I need the script to be accessible within the container. I am guessing that I might need shared storage when using cmdline, is there a better way to achieve this? Any pointers would be really helpful.

Thanks.

Asked By: Rahul

||

Answers:

You could use /etc/issue file for Debian/Ubuntu:

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

or /etc/redhat-release for 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)
Answered By: pie

The Filesystem Hierarchy Standard has a standard definition for /etc/os-release, which should be available on most distributions:

The /etc/os-release and /usr/lib/os-release files contain operating system identification data.

The basic file format of os-release is a newline-separated list of environment-like shell-compatible variable assignments. It is possible to source the configuration from shell scripts.

This means you can just source /etc/os-release and use $NAME or $ID to identify the distribution. As an example, on Fedora it looks like this:

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

On Debian:

% source /etc/os-release
% echo $NAME
Debian GNU/Linux
% echo $ID
debian
Answered By: morxa

You should use following cmd to detect Ubuntu release name:

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

For Ubuntu docker images I am using following cmds when I need to add multiverse to apt.source.lists and haven’t duplicate lines:

RUN export UBUNTU_RELEASE=$(lsb_release  -sc || cat /etc/*-release|grep -oP  'CODENAME=Kw+$'|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 && 

You should use following cmd to detect Debian release name ( I am using it for my docker images):

export DEBIAN_RELEASE=$(awk -F'[" ]' '/VERSION=/{print $3}'  /etc/os-release | tr -cd '[[:alnum:]]._-' ) && 
     [[ "x${DEBIAN_RELEASE}" = "x" ]] && export DEBIAN_RELEASE="unstable" 
Answered By: Valeriy Solovyov

Expanding on @morxa’s answer and comment, some sh doesn’t have source defined. In such case we can use

grep NAME /etc/*-release

to be able to see what the OS is. Usually the PRETTY_NAME can tell the whole name:

PRETTY_NAME="Ubuntu 20.04 LTS"
Answered By: nonopolarity

Most answers give us OS release, but the question is also concern docker.

I’m lazy, especially when I have more than 20 images, so:

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

And most images have results:

> 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"
> ...
Answered By: Qinsi

If you don’t want to do any action on the image you mat try to figure out winch os it base on the firsts layers .

for finding the layers just type

docker inspect <image name>

then see the layer section.
then you can make a list of each layer belong to which base image

Answered By: daniel
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.