{"id":13416267,"url":"https://github.com/google/docker-explorer","last_synced_at":"2025-08-13T01:23:51.697Z","repository":{"id":37734482,"uuid":"133632679","full_name":"google/docker-explorer","owner":"google","description":"A tool to help forensicate offline docker acquisitions","archived":false,"fork":false,"pushed_at":"2024-10-04T07:44:31.000Z","size":12027,"stargazers_count":533,"open_issues_count":11,"forks_count":46,"subscribers_count":20,"default_branch":"main","last_synced_at":"2025-01-07T16:07:46.530Z","etag":null,"topics":["docker","forensics"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/google.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2018-05-16T08:11:59.000Z","updated_at":"2024-12-19T12:49:24.000Z","dependencies_parsed_at":"2022-09-06T07:11:33.246Z","dependency_job_id":"9a49b62f-41a9-4964-8fa5-76736c93d601","html_url":"https://github.com/google/docker-explorer","commit_stats":{"total_commits":99,"total_committers":3,"mean_commits":33.0,"dds":0.06060606060606055,"last_synced_commit":"235f019f3d52f6d04b94fae75c3e8d3952c29a60"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Fdocker-explorer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Fdocker-explorer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Fdocker-explorer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Fdocker-explorer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/google","download_url":"https://codeload.github.com/google/docker-explorer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243663514,"owners_count":20327300,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","forensics"],"created_at":"2024-07-30T21:00:56.210Z","updated_at":"2025-08-13T01:23:51.660Z","avatar_url":"https://github.com/google.png","language":"Python","readme":"# Docker Explorer\n\nThis project helps a forensics analyst explore offline Docker filesystems.\n\nThis is not an officially supported Google product.\n\nIf you're looking for similar capabilities on [Containerd](https://containerd.io/)\nsystems, feel free to check [https://github.com/google/container-explorer](https://github.com/google/container-explorer).\n\n## Overview\n\nWhen analyzing a system where a Docker container has been compromised, it can\nbe useful to have the same view of the filesystem as the container's.\n\nDocker uses layered backend filesystems like\n[AuFS](https://jpetazzo.github.io/assets/2015-03-03-not-so-deep-dive-into-docker-storage-drivers.html)\nor OverlayFS.\n\nEach layer is actually stored on the host's filesystem as multiple folders, and\nsome JSON files are used by Docker to know what is what;\n\n## Installation\n\n### PPA\n\nA .deb package is available in the [GIFT PPA](https://launchpad.net/~gift)\n\n```\nadd-apt-repository ppa:gift/stable\napt update\napt install docker-explorer-tools\n```\n\n### PyPI\n\nThis project is released on [PyPi](https://pypi.org/project/docker-explorer/).\n\n```\nvirtualenv docker-explorer ; cd docker-explorer ; source bin/activate\npip install docker-explorer\n```\n\n### Source\n\nYou can clone this repository, as running the script doesn't require any\nexternal dependency.\n\n## Usage\n\nFor the forensicator, this usually goes:\n\n0. find the interesting container ID\n0. mount the container's filesystem in `/mnt/container`\n0. `log2timeline.py /tmp/container.plaso /mnt/container`\n0. or `ls -lta /mnt/container/tmp`\n\n### List the running containers\n\nOn a live host running the compromised container you would run:\n\n```\n# docker ps\nCONTAINER ID        IMAGE               COMMAND             CREATED         STATUS              PORTS               NAMES\n7b02fb3e8a66        busybox             \"sleep 10d\"         19 hours ago    Up 19 hours                             dreamy_snyder\n```\n\nIf you mount the disk image of the same host in `/mnt/root`, you can use `de.py`\nto access the same information:\n\n```\n# de.py -r /mnt/root/var/lib/docker list running_containers\n[\n    {\n        \"container_id\": \"7b02fb3e8a665a63e32b909af5babb7d6ba0b64e10003b2d9534c7d5f2af8966\",\n        \"image_id\": \"7968321274dc6b6171697c33df7815310468e694ac5be0ec03ff053bb135e768\",\n        \"image_name\": \"busybox\",\n        \"start_date\": \"2016-09-16T11:50:15.253796\"\n    }\n]\n```\n\n### Mount the container's filesystem:\n\nOn a live host running the compromised container you would run:\n\n```\n# find ID of your running container:\ndocker ps\n\n# create image (snapshot) from container filesystem\ndocker commit 12345678904b5 mysnapshot\n\n# explore this filesystem using bash (for example)\ndocker run -t -i mysnapshot /bin/bash\n```\n\nIf you mount the disk image of the same host in `/mnt/root`, you can use `de.py`\nto access the same information:\n\n```\n# de.py -r /tmp/ mount 7b02fb3e8a665a63e32b909af5babb7d6ba0b64e10003b2d9534c7d5f2af8966 /tmp\nYou'll needs the aufs-tools package. If you install aufs-tools, I can run these for you.\n```\n\nWhoops... Let's try again\n\n```\n# apt install aufs-tools\n# de.py -r /tmp/ mount 7b02fb3e8a665a63e32b909af5babb7d6ba0b64e10003b2d9534c7d5f2af8966 /tmp/test\nmount -t aufs -o ro,br=/tmp/docker/aufs/diff/b16a494082bba0091e572b58ff80af1b7b5d28737a3eedbe01e73cd7f4e01d23=ro+wh none /tmp/test\nmount -t aufs -o ro,remount,append:/tmp/docker/aufs/diff/b16a494082bba0091e572b58ff80af1b7b5d28737a3eedbe01e73cd7f4e01d23-init=ro+wh none /tmp/test\nmount -t aufs -o ro,remount,append:/tmp/docker/aufs/diff/d1c54c46d331de21587a16397e8bd95bdbb1015e1a04797c76de128107da83ae=ro+wh none /tmp/test\nroot@test-VirtualBox:~# ls /tmp/test\nbin  dev  etc  home  proc  root  sys  tmp  usr  var\n```\n\n### Show a container's image history\n\nOn the live host:\n\n```\n# docker history 7968321274dc6b6171697c33df7815310468e694ac5be0ec03ff053bb135e768\nIMAGE               CREATED             CREATED BY                                      SIZE                COMMENT\n7968321274dc        4 weeks ago         /bin/sh -c #(nop)  CMD [\"sh\"]                   0 B\n\u003cmissing\u003e           4 weeks ago         /bin/sh -c #(nop) ADD file:707e63805c0be1a226   1.11 MB\n```\n\n\nOn a disk image mounted in\n`/mnt/root`:\n\n```\n# de.py -r /mnt/root/var/lib/docker history 7b02fb3e8a665a63e32b909af5babb7d6ba0b64e10003b2d9534c7d5f2af8966\n{\n    \"sha256:7968321274dc6b6171697c33df7815310468e694ac5be0ec03ff053bb135e768\": {\n        \"container_cmd\": \"/bin/sh -c #(nop)  CMD [\\\"sh\\\"]\",\n        \"created_at : \"2018-09-20T18:41:05.770133\",\n        \"size\" : 0\n    }\n}\n```\n\n## Troubleshooting\n\nIf on your Ubuntu system you get the errors:\n\n```\nmount: unknown filesystem type 'aufs'\n/sbin/mount.aufs:proc_mnt.c:96: /mnt/aufs: Invalid argument\n/sbin/mount.aufs:proc_mnt.c:96: /mnt/aufs: Invalid argument\n/sbin/mount.aufs:proc_mnt.c:96: /mnt/aufs: Invalid argument\n/sbin/mount.aufs:proc_mnt.c:96: /mnt/aufs: Invalid argument\n/sbin/mount.aufs:proc_mnt.c:96: /mnt/aufs: Invalid argument\n/sbin/mount.aufs:proc_mnt.c:96: /mnt/aufs: Invalid argument\n/sbin/mount.aufs:proc_mnt.c:96: /mnt/aufs: Invalid argument\n/sbin/mount.aufs:proc_mnt.c:96: /mnt/aufs: Invalid argument\n/sbin/mount.aufs:proc_mnt.c:96: /mnt/aufs: Invalid argument\n....\n```\n\nTry this:\n\n```\nsudo apt-get install linux-image-extra-$(uname -r)\n```\n\n## Maintainer notes\n\n### Gift PPA push\n\nMake sure the following is installed:\n```\nsudo apt install dh-python flex byacc quilt python3-all-dev libdistro-info-perl\n```\n\nFor the GPG signing part, running over SSH with a gpg-agent running might\nconfuse gpg and ask for the passphrase on the $DISPLAY. To prevent this, you can\nrun `gpgconf --kill gpg-agent`.\n\nMake a new version tag:\n```\nDATE=\"$(date +%Y%m%d)\"\ngit checkout main\ngit pull upstream main\ngit tag \"${DATE}\"\ngit push upstream \"${DATE}\"\n```\n\nBuild with [l2tdevtools](https://github.com/log2timeline/l2tdevtools).\n```\ncd /tmp\ngit clone https://github.com/log2timeline/l2tdevtools\n```\n\nMake the build environment:\n```\nmkdir /tmp/build ; cd /tmp/build\n```\n\nFirst we need 2 files, `post-dpkg-source.sh`:\n```\ncat \u003c\u003cEOF \u003epost-dpkg-source.sh\nPROJECT=\\$1;\nVERSION=\\$2;\nVERSION_SUFFIX=\\$3;\nDISTRIBUTION=\\$4;\nARCHITECTURE=\\$5;\n\ndput ppa:docker-explorer-dev-team_staging ../\\${PROJECT}_\\${VERSION}-1\\${VERSION_SUFFIX}~\\${DISTRIBUTION}_\\${ARCHITECTURE}.changes\nEOF\n```\n\nand `prep-dpkg-source.sh`:\n```\ncat \u003c\u003cEOF \u003eprep-dpkg-source.sh\nexport NAME=\"Docker-Explorer devs\";\nexport EMAIL=\"docker-explorer-devs@google.com\";\n\nPROJECT=\\$1;\nVERSION=\\$2;\nVERSION_SUFFIX=\\$3;\nDISTRIBUTION=\\$4;\nARCHITECTURE=\\$5;\n\ndch --preserve -v \\${VERSION}-1\\${VERSION_SUFFIX}~\\${DISTRIBUTION} --distribution \\${DISTRIBUTION} --urgency low \"Modifications for PPA release.\"\nEOF\n```\n\nThese are also stored in `/tmp/build`\n\nThen go to https://github.com/google/docker-explorer/releases and create a new\nrelease.\n\nStart the build:\n\n```\nPYTHONPATH=. python3 tools/build.py --build-directory=/tmp/build/  --project docker-explorer dpkg-source --distributions focal,jammy,noble\n```\n\nThen upload the packages to the PPA:\n\n```\ncd /tmp/build/\ndput ppa:docker-explorer-devs_staging docker-explorer_\u003cVERSION\u003e_source.changes\n```\n\nThen wait for launchpad to build the package, and move it from\nppa:docker-explorer-dev-team_staging to ppa:gift_stable, by going to\n[https://launchpad.net/~docker-explorer-devs/+archive/ubuntu/staging/+copy-packages](https://launchpad.net/~docker-explorer-devs/+archive/ubuntu/staging/+copy-packages)\n\n\n\n\n### Upload to PyPi\n\nFirst make sure the proper version is set in `docker-explorer/__init__.py`.\n\nThen run\n\n```\nsudo apt install twine\npython3 setup.py sdist\npython3 -m twine upload  dist/*\n```\n","funding_links":[],"categories":["Container Operations","Tools","\u003ca id=\"e1fc1d87056438f82268742dc2ba08f5\"\u003e\u003c/a\u003e事件响应\u0026\u0026取证\u0026\u0026内存取证\u0026\u0026数字取证","Python","Challenges","\u003ca id=\"ecb63dfb62722feb6d43a9506515b4e3\"\u003e\u003c/a\u003e新添加"],"sub_categories":["Security","Docker Forensics","\u003ca id=\"1fc5d3621bb13d878f337c8031396484\"\u003e\u003c/a\u003e取证\u0026\u0026Forensics\u0026\u0026数字取证\u0026\u0026内存取证"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoogle%2Fdocker-explorer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgoogle%2Fdocker-explorer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoogle%2Fdocker-explorer/lists"}