3
\$\begingroup\$

I have written a piece of code in Python for removing the docker images which are not tagged only:

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
release             3.1                 b6bf9d19cc6c        5 hours ago         869MB
release             3.2                 b6bf9d19cc6c        5 hours ago         869MB
<none>              <none>              3dfdfcb0769d        6 hours ago         433MB
<none>              <none>              d505190470fd        6 hours ago         433MB
<none>              <none>              979a42368814        7 hours ago         433MB
<none>              <none>              f8bcf895ffce        7 hours ago         433MB
<none>              <none>              8c1ed97822da        7 hours ago         433MB
release             1.0                 36e9ea407082        7 hours ago         433MB
ubuntu              16.04               6a2f32de169d        6 days ago          117MB
vault               latest              144fecac962b        3 weeks ago         64.4MB

Python code:

import subprocess

output = subprocess.Popen(["docker", "images"], stdout=subprocess.PIPE)

result = output.communicate()[0].split("\n")
image_list = []

for line in result[1:]:

    if ("<none>" == line.split("  ")[0]):
        image_list.append(filter(None,line.split("  "))[2])

for image in image_list:
     #Piping both stdout and stderr to stdout.
     output = subprocess.Popen(["docker", "rmi", "-f", image], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
     print(output.communicate()[0])

Final output:

docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
release             3.1                 b6bf9d19cc6c        5 hours ago         869MB
release             3.2                 b6bf9d19cc6c        5 hours ago         869MB
release             1.0                 36e9ea407082        7 hours ago         433MB
ubuntu              16.04               6a2f32de169d        6 days ago          117MB
vault               latest              144fecac962b        3 weeks ago         64.4MB

Please let me know if the code can be optimized or can be written in a more pythonic way.

\$\endgroup\$
4
  • \$\begingroup\$ I'm not sure Python is the tool for the job - you can do it on the command line with docker rmi $(docker images | grep "^<none>" | awk "{print $3}"). \$\endgroup\$
    – jonrsharpe
    Apr 21, 2017 at 9:45
  • \$\begingroup\$ the reason for doing the job in python is getting practice in python. \$\endgroup\$ Apr 21, 2017 at 9:47
  • 1
    \$\begingroup\$ I didn't want to make this an answer because it isn't directly reviewing the code, but have you considered using docker-py? (docker-py.readthedocs.io/en/stable) That might be better than opening a subprocess to call out to the docker command-line client. \$\endgroup\$
    – Flavin
    Apr 21, 2017 at 13:57
  • \$\begingroup\$ Thanks for sharing the info, I was not knowing about the docker library. \$\endgroup\$ Apr 21, 2017 at 16:31

1 Answer 1

2
\$\begingroup\$

I would split the line of the output once and re-use that. Also, if you don't pass a separator to str.split, it will split on whitespace, so "A B C".split() == ['A', 'B', 'C'].

import subprocess

output = subprocess.Popen(["docker", "images"], stdout=subprocess.PIPE)
result = output.communicate()[0].split("\n")

image_list = []
for line in result[1:]:
    line = line.split()
    if line[0] == "<none>":
        image_list.append(line[2])

for image in image_list:
     #Piping both stdout and stderr to stdout.
     output = subprocess.Popen(["docker", "rmi", "-f", image], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
     print(output.communicate()[0])

I would probably change if line[0] == "<none>" to if line[1] == "<none>" to adhere more closely to what you want to do. I'm not sure if it can happen that the repository is not none, but the tag is.

I would also change the grouping slightly, so that things which logically belong together are grouped. This is the first step towards putting them into their own functions, which could be slightly overkill here, but would make it a lot easier to re-use parts of this:

import subprocess


def get_docker_images():
    output = subprocess.Popen(["docker", "images"], stdout=subprocess.PIPE)
    return map(str.split, output.communicate()[0].split("\n")[1:-1])


def no_tag(images):
    for image in images:
        if image[1] == "<none>":
            yield image


def delete_images(images):
    for image in images:
        output = subprocess.Popen(["docker", "rmi", "-f", image[2]],
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.STDOUT)
        print(output.communicate()[0])


if __name__ == '__main__':
    delete_images(no_tag(get_docker_images()))
\$\endgroup\$
2
  • \$\begingroup\$ 1) reason for using separator in split(" ")(with 2 white spaces) is because the string "3 hours ago" is also getting separated as 3 different strings, which I was not looking for. Just in case if I want to use that string for another purpose. \$\endgroup\$ Apr 21, 2017 at 13:19
  • \$\begingroup\$ @Raghavendra Which is quite easy to change...In the function version you will have to write a lambda l: l.split(" ") function instead of the simple str.split, though... \$\endgroup\$
    – Graipher
    Apr 21, 2017 at 13:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.