37 Commits

Author SHA1 Message Date
Red5d
d976d520b4 Merge pull request #32 from hgghyxo/patch-1
Update README.md
2022-02-24 11:14:25 -05:00
hgghyxo
ec211717ed Update README.md
adding a oneliner to print out all containers
2022-02-24 11:49:46 +01:00
Red5d
4e8ff192dc Updates about ARM support, dependency listing, and formatting/wording 2021-08-07 14:06:52 -04:00
Red5d
8ada367b9e Enable generating compose files for containers that aren't running. 2021-08-07 13:51:02 -04:00
Red5d
94ca597f3d Merge pull request #23 from LunaticMuch/fix/six-module
fix: six module missing
Not sure why this wasn't necessary before, but it definitely needs it now.
2021-08-07 13:40:14 -04:00
Red5d
0ed2f306cc Workaround for buildx not liking the capital letter in my username 2021-08-07 13:27:21 -04:00
Red5d
6415678751 Merge pull request #18 from doob187/master
I've added the secret key to the repo. Sorry this has taken a while. Life's been really busy and I forgot about this one.
2021-08-07 13:06:49 -04:00
doob187
4b5e27cf29 Merge branch 'Red5d:master' into master 2021-08-07 08:31:16 +02:00
LunaticMuch
d90e2d5389 fix: six module missing 2021-08-02 09:32:23 +01:00
Red5d
881b7979d5 Fix malformed 'devices' values 2021-07-28 23:43:07 -04:00
Red5d
a1f2aabdee Fix lines that depend on the 'networks' key being in values list 2021-07-28 23:19:19 -04:00
Red5d
d8e5aacf20 Exclude the 'networks' key if only the default bridge network is present 2021-07-28 23:13:17 -04:00
Red5d
0556a35376 Remove fields that are invalid in the compose v3 spec 2021-07-28 23:03:54 -04:00
doob187
046f0e9da7 Update Dockerfile 2021-05-29 08:11:47 +02:00
doob187
9c3e01d167 Create docker.yml 2021-05-29 08:04:46 +02:00
Red5d
9f3960defd Merge pull request #14 from akshaysalunke13/master
Fix yaml output to reflect latest docker-compose reference.
2021-03-15 10:28:46 -04:00
Akshay
98704a81b6 Fix 'networks' in yaml
fix opts following official compose reference

[docker-compose reference](https://docs.docker.com/compose/compose-file/compose-file-v3/)
2021-03-14 21:05:41 +11:00
Akshay Salunke
a3ff6534ab ignore ds_store file for mac 2021-03-14 17:50:13 +11:00
akshay-scalegrowth
555f1f90b3 Added requirements.txt for required packages 2021-03-14 16:29:26 +11:00
akshay-scalegrowth
09f14bceca Added gitignore 2021-03-14 16:29:06 +11:00
Red5d
e0f6c83bc4 Merge pull request #13 from rootrider/master
Update README.md
2020-10-22 19:20:42 -04:00
Joel
7fe7a07fb5 Update README.md
correct the link to the newer docker python module
2020-10-22 14:54:00 -07:00
Red5d
4eb8d97536 Fixed typo in compose file version setting example. 2018-12-20 21:04:40 -05:00
Red5d
b78da97768 Add additional networks stanza at the bottom of the output to support the networks attached to the container(s). 2018-08-24 19:44:24 -04:00
Red5d
e5ac520ff6 Support networks and network aliases. 2018-08-24 17:49:55 -04:00
Red5d
9827c4488d Updated README with new feature and usage information. 2018-07-27 20:44:14 -04:00
Red5d
800b088cea Update setup script to use new docker module, bump minimum module versions, and overall app version. 2018-07-27 20:21:35 -04:00
Red5d
9e0fa327ee Update script to use new module version, output compose file version 3, and be able to generate a combined file for multiple containers. 2018-07-27 20:20:41 -04:00
Red5d
f22f154fe9 Merge pull request #6 from smokes2345/patch-1
Update autocompose.py
2018-07-15 12:22:01 -04:00
Matt Davidson
bdb38eecac Update autocompose.py
Trying to iterate on cinspect['HostConfig']['PortBindings'] when it is equal to 'None' produces a TypeError
2018-07-15 11:13:38 -04:00
Red5d
f3f2eca906 Adjust format of example for clarity 2018-06-27 23:16:48 -04:00
Red5d
05bab6fda0 Merge pull request #4 from docwhat/patch-1
Update README.md
2018-03-20 14:34:57 -04:00
Christian Höltje
2a1b25e4f4 Update README.md
fixed image name.
2018-03-20 11:50:43 -04:00
Red5d
40ec3f9b42 Update image tag name. 2018-02-12 14:34:25 -05:00
Red5d
858b187e75 Merge pull request #2 from mogensen/master
Adding Dockerfile to run docker-autocompose as a container
2017-09-12 09:15:16 -04:00
Frederik Mogensen
b71078f68b Updated Readme 2017-09-12 12:41:05 +02:00
Frederik Mogensen
83bc0afad6 Docker file for running autocompose in docker 2017-09-12 12:15:46 +02:00
7 changed files with 209 additions and 61 deletions

77
.github/workflows/docker.yml vendored Normal file
View File

@@ -0,0 +1,77 @@
name: Build Multi Stage Docker Image
on:
push:
branches-ignore:
- 'dependabot/**'
schedule:
- cron: '0 5 * * *'
jobs:
GHRC:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
- uses: FranzDiebold/github-env-vars-action@v2.3.0
- name: Print environment variables
run: |
echo "CI_REPOSITORY_NAME=$CI_REPOSITORY_NAME"
- name: Prepare GHRC.io
id: prep
run: |
REPO=$CI_REPOSITORY_NAME
OWNER="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')"
DOCKER_IMAGE=${OWNER}/${REPO}
if [ "$CI_REF_NAME" == "master" ];then VERSION=latest;fi
if [ "$CI_REF_NAME" == "dev" ];then VERSION=mightly;fi
if [ "$CI_REF_NAME" == "dockserver" ];then VERSION=dockserver;fi
TAGS="${DOCKER_IMAGE}:${VERSION}"
echo ::set-output name=tags::${TAGS}
echo ::set-output name=title::${GITHUB_REPOSITORY}
echo ::set-output name=version::${VERSION}
echo ::set-output name=created::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
with:
platforms: linux/amd64,linux/armhf,linux/arm64
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1.3.0
- name: Cache Docker layers
uses: actions/cache@v2.1.6
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v1.9.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.CR_PAT }}
- name: Build and push GHRC.io
id: docker_build
uses: docker/build-push-action@v2.5.0
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/armhf,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ghcr.io/${{ steps.prep.outputs.tags }}
labels: |
org.opencontainers.image.title=${{ steps.prep.outputs.title }}
org.opencontainers.image.version=${{ steps.prep.outputs.version }}
org.opencontainers.image.created=${{ steps.prep.outputs.created }}
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
venv
.vscode
.DS_Store

10
Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM python:3-alpine
LABEL org.opencontainers.image.source https://github.com/Red5d/docker-autocompose
WORKDIR /usr/src/app
COPY . .
RUN python ./setup.py install
ENTRYPOINT [ "python", "./autocompose.py" ]

View File

@@ -1,18 +1,48 @@
# docker-autocompose
Generates a docker-compose yaml definition from a running container.
Generates a docker-compose yaml definition from a docker container.
Required Modules:
* [pyaml](https://pypi.python.org/pypi/pyaml/)
* [docker-py](https://pypi.python.org/pypi/docker-py)
* [pyaml](https://pypi.python.org/project/pyaml/)
* [docker](https://pypi.python.org/project/docker)
* [six](https://pypi.python.org/project/six)
Example Usage:
sudo python autocompose.py container-name
sudo python autocompose.py <container-name-or-id>
Generate a compose file for multiple containers together:
sudo python autocompose.py apache-test mysql-test
The script defaults to outputting to compose file version 3, but use "-v 1" to output to version 1:
sudo python autocompose.py -v 1 apache-test
Outputs a docker-compose compatible yaml structure:
Outputs a docker-compose compatible yaml structure.
[docker-compose reference](https://docs.docker.com/compose/)
[docker-compose yaml file specification](https://docs.docker.com/compose/compose-file/)
While experimenting with various docker containers from the Hub, I realized that I'd started several containers with complex options for volumes, ports, environment variables, etc. and there was no way I could remember all those commands without referencing the Hub page for each image if I needed to delete and re-create the container (for updates, or if something broke).
With this tool, I can easily generate docker-compose files for managing the containers that I've set up manually.
## Docker Usage
You can use this tool from a docker container by either cloning this repo and building the image or using the [automatically generated image on GitHub](https://github.com/Red5d/docker-autocompose/pkgs/container/docker-autocompose)
Pull the image from GitHub (supports both x86 and ARM)
docker pull ghcr.io/red5d/docker-autocompose:latest
Use the new image to generate a docker-compose file from a running container or a list of space-separated container names or ids:
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/red5d/docker-autocompose <container-name-or-id> <additional-names-or-ids>...
To print out all containers in a docker-compose format:
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/red5d/docker-autocompose $(docker ps -aq)

View File

@@ -1,81 +1,106 @@
#! /usr/bin/env python
import pyaml, argparse, sys
from docker import Client
import sys, argparse, pyaml, docker
from collections import OrderedDict
def main():
parser = argparse.ArgumentParser(description='Generate docker-compose yaml definition from running container.')
parser.add_argument('cname', type=str, help='The name of the container to process.')
parser.add_argument('-v', '--version', type=int, default=3, help='Compose file version (1 or 3)')
parser.add_argument('cnames', nargs='*', type=str, help='The name of the container to process.')
args = parser.parse_args()
generate(args)
struct = {}
networks = []
for cname in args.cnames:
cfile, networks = generate(cname)
struct.update(cfile)
render(struct, args, networks)
def render(struct, args, networks):
# Render yaml file
if args.version == 1:
pyaml.p(OrderedDict(struct))
else:
pyaml.p(OrderedDict({'version': '"3"', 'services': struct, 'networks': networks}))
def generate(args):
c = Client(base_url='unix://var/run/docker.sock')
def generate(cname):
c = docker.from_env()
try:
cid = [x['Id'] for x in c.containers() if args.cname in x['Names'][0]][0]
cid = [x.short_id for x in c.containers.list(all=True) if cname == x.name or x.short_id in cname][0]
except IndexError:
print("That container is not running.")
print("That container is not available.")
sys.exit(1)
cinspect = c.inspect_container(cid)
cattrs = c.containers.get(cid).attrs
# Build yaml dict structure
cfile = {}
cfile[args.cname] = {}
ct = cfile[args.cname]
cfile[cattrs['Name'][1:]] = {}
ct = cfile[cattrs['Name'][1:]]
values = {
'cap_add': cinspect['HostConfig']['CapAdd'],
'cap_drop': cinspect['HostConfig']['CapDrop'],
'cgroup_parent': cinspect['HostConfig']['CgroupParent'],
'container_name': args.cname,
'devices': cinspect['HostConfig']['Devices'],
'dns': cinspect['HostConfig']['Dns'],
'dns_search': cinspect['HostConfig']['DnsSearch'],
'environment': cinspect['Config']['Env'],
'extra_hosts': cinspect['HostConfig']['ExtraHosts'],
'image': cinspect['Config']['Image'],
'labels': cinspect['Config']['Labels'],
'links': cinspect['HostConfig']['Links'],
'log_driver': cinspect['HostConfig']['LogConfig']['Type'],
'log_opt': cinspect['HostConfig']['LogConfig']['Config'],
'net': cinspect['HostConfig']['NetworkMode'],
'security_opt': cinspect['HostConfig']['SecurityOpt'],
'ulimits': cinspect['HostConfig']['Ulimits'],
'volumes': cinspect['HostConfig']['Binds'],
'volume_driver': cinspect['HostConfig']['VolumeDriver'],
'volumes_from': cinspect['HostConfig']['VolumesFrom'],
'cpu_shares': cinspect['HostConfig']['CpuShares'],
'cpuset': cinspect['HostConfig']['CpusetCpus']+','+cinspect['HostConfig']['CpusetMems'],
'entrypoint': cinspect['Config']['Entrypoint'],
'user': cinspect['Config']['User'],
'working_dir': cinspect['Config']['WorkingDir'],
'domainname': cinspect['Config']['Domainname'],
'hostname': cinspect['Config']['Hostname'],
'ipc': cinspect['HostConfig']['IpcMode'],
'mac_address': cinspect['NetworkSettings']['MacAddress'],
'mem_limit': cinspect['HostConfig']['Memory'],
'memswap_limit': cinspect['HostConfig']['MemorySwap'],
'privileged': cinspect['HostConfig']['Privileged'],
'restart': cinspect['HostConfig']['RestartPolicy']['Name'],
'read_only': cinspect['HostConfig']['ReadonlyRootfs'],
'stdin_open': cinspect['Config']['OpenStdin'],
'tty': cinspect['Config']['Tty']
'cap_add': cattrs['HostConfig']['CapAdd'],
'cap_drop': cattrs['HostConfig']['CapDrop'],
'cgroup_parent': cattrs['HostConfig']['CgroupParent'],
'container_name': cattrs['Name'][1:],
'devices': [],
'dns': cattrs['HostConfig']['Dns'],
'dns_search': cattrs['HostConfig']['DnsSearch'],
'environment': cattrs['Config']['Env'],
'extra_hosts': cattrs['HostConfig']['ExtraHosts'],
'image': cattrs['Config']['Image'],
'labels': cattrs['Config']['Labels'],
'links': cattrs['HostConfig']['Links'],
#'log_driver': cattrs['HostConfig']['LogConfig']['Type'],
#'log_opt': cattrs['HostConfig']['LogConfig']['Config'],
'logging': {'driver': cattrs['HostConfig']['LogConfig']['Type'], 'options': cattrs['HostConfig']['LogConfig']['Config']},
'networks': {x for x in cattrs['NetworkSettings']['Networks'].keys() if x != 'bridge'},
'security_opt': cattrs['HostConfig']['SecurityOpt'],
'ulimits': cattrs['HostConfig']['Ulimits'],
'volumes': cattrs['HostConfig']['Binds'],
'volume_driver': cattrs['HostConfig']['VolumeDriver'],
'volumes_from': cattrs['HostConfig']['VolumesFrom'],
'entrypoint': cattrs['Config']['Entrypoint'],
'user': cattrs['Config']['User'],
'working_dir': cattrs['Config']['WorkingDir'],
'domainname': cattrs['Config']['Domainname'],
'hostname': cattrs['Config']['Hostname'],
'ipc': cattrs['HostConfig']['IpcMode'],
'mac_address': cattrs['NetworkSettings']['MacAddress'],
'privileged': cattrs['HostConfig']['Privileged'],
'restart': cattrs['HostConfig']['RestartPolicy']['Name'],
'read_only': cattrs['HostConfig']['ReadonlyRootfs'],
'stdin_open': cattrs['Config']['OpenStdin'],
'tty': cattrs['Config']['Tty']
}
# Populate devices key if device values are present
if cattrs['HostConfig']['Devices']:
values['devices'] = [x['PathOnHost']+':'+x['PathInContainer'] for x in cattrs['HostConfig']['Devices']]
networks = {}
if values['networks'] == set():
del values['networks']
else:
networklist = c.networks.list()
for network in networklist:
if network.attrs['Name'] in values['networks']:
networks[network.attrs['Name']] = {'external': (not network.attrs['Internal'])}
# Check for command and add it if present.
if cinspect['Config']['Cmd'] != None:
values['command'] = " ".join(cinspect['Config']['Cmd']),
if cattrs['Config']['Cmd'] != None:
values['command'] = " ".join(cattrs['Config']['Cmd']),
# Check for exposed/bound ports and add them if needed.
try:
expose_value = list(cinspect['Config']['ExposedPorts'].keys())
ports_value = [cinspect['HostConfig']['PortBindings'][key][0]['HostIp']+':'+cinspect['HostConfig']['PortBindings'][key][0]['HostPort']+':'+key for key in cinspect['HostConfig']['PortBindings']]
expose_value = list(cattrs['Config']['ExposedPorts'].keys())
ports_value = [cattrs['HostConfig']['PortBindings'][key][0]['HostIp']+':'+cattrs['HostConfig']['PortBindings'][key][0]['HostPort']+':'+key for key in cattrs['HostConfig']['PortBindings']]
# If bound ports found, don't use the 'expose' value.
if (ports_value != None) and (ports_value != "") and (ports_value != []) and (ports_value != 'null') and (ports_value != {}) and (ports_value != "default") and (ports_value != 0) and (ports_value != ",") and (ports_value != "no"):
@@ -87,7 +112,7 @@ def generate(args):
else:
values['expose'] = expose_value
except KeyError:
except (KeyError, TypeError):
# No ports exposed/bound. Continue without them.
ports = None
@@ -97,8 +122,8 @@ def generate(args):
if (value != None) and (value != "") and (value != []) and (value != 'null') and (value != {}) and (value != "default") and (value != 0) and (value != ",") and (value != "no"):
ct[key] = value
# Render yaml file
pyaml.p(cfile)
return cfile, networks
if __name__ == "__main__":
main()

3
requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
pyaml==20.4.0
docker==4.4.4
six==1.16.0

View File

@@ -1,14 +1,14 @@
from setuptools import setup, find_packages
setup(
name = "docker-autocompose",
version = "1.0.1",
version = "1.2.0",
description = "Generate a docker-compose yaml definition from a running container",
url = "https://github.com/Red5d/docker-autocompose",
author = "Red5d",
license = "GPLv2",
keywords = "docker yaml container",
packages = find_packages(),
install_requires = ['pyaml>=15.8.2', 'docker-py>=1.6.0'],
install_requires = ['pyaml>=17.12.1', 'docker>=3.4.1','six>=1.16.0'],
scripts = ['autocompose.py'],
entry_points={
'console_scripts': [