Package: python-docker
python-dockerA pure python implementation to build docker images withoutdockerand provide a python api for interacting with docker
registries.Examples using LibraryDownloading docker images without docker!frompython_docker.registryimportRegistryregistry=Registry()image=registry.pull_image('frolvlad/alpine-glibc','latest')Modify docker image from filesystemfrompython_docker.baseimportImagefrompython_docker.registryimportRegistryregistry=Registry()image=registry.pull_image('continuumio/miniconda3','latest')image.remove_layer()image.name='this-is-a-test'image.add_layer_path('./')image.add_layer_contents({'/this/is/a/test1':b'this is test 1','/this/is/a/test2':b'this is test 2'})image.layers[0].config['Env'].append('FOO=BAR')# write docker image to filesystemimage.write_filename('example-docker-image.tar')# run docker image (does require docker)image.run(['cat /this/is/a/test1'])The above example shows how you can update a docker image after
pulling it from a registry. Additionally there is alazyoption in
thepull_imagemethod. This allows you to modify docker images
without actually having to download all the layers. This is an
important feature when needing to add a small layer to a larger gpu
image that is several GBs.frompython_docker.baseimportImagefrompython_docker.registryimportRegistryregistry=Registry()image=registry.pull_image('continuumio/miniconda3','latest',lazy=True)# do the same actions as the example above# difference is that the layers are lazily downloaded# only when needed in the `image.write_filename`# and `image.run`.registry.push_image(image)# push_image does not require downloading the layersDevelopmentDependenciesinstall docker-composeinstall condaInstall the development environmentcondaenvcreate-fenvironment-dev.yamlTestingdocker-composeup-d
pytestHow does this work?Turns out that docker images are just a tar collection of files. There
are several versions of the spec. Forv1.0the specification isdefined
here.
Instead of writing down the spec lets look into a single docker image.dockerpullubuntu:latest
dockersaveubuntu:latest-o/tmp/ubuntu.tarList the directory structure of the docker image. Notice how it is a
collection oflayer.tarwhich is a tar archive of filesystems. And
several json files.VERSIONfile is always1.0currently.tar-tvf/tmp/ubuntu.tarDockerhub happens to export docker images in av1-v1.2compatible
format. Lets only look at the files important forv1. Repositories
tells the layer to use as the layer head of the current name/tag.tar-xf/tmp/ubuntu.tar$filenamecat$filename|python-mjson.toolFor each layer there are three files:VERSION,layer.tar, andjson.tar-xf/tmp/ubuntu.tar$filenamecat$filenametar-xf/tmp/ubuntu.tar$filenamecat$filename|python-mjson.toolLooking at layer metadata.{"id":"93935bf1450219e4351893e546b97b4584083b01d19daeba56cab906fc75fc1c","created":"1969-12-31T19:00:00-05:00","container_config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Cmd":null,"Image":"","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"os":"linux"}Looking at the layer filesystem.tar-xf/tmp/ubuntu.tar$filenametar-tvf$filename|headReferencesDocker Registry API SpecificationDocker Image SpecificationSummaryRegistry V2 Specification