|
#! /usr/bin/env python |
|
|
|
# Copy of https://github.com/Red5d/docker-autocompose dirty hacked with some fixes for dates and |
|
# possiblity to create docker command lines from the existing containers by using the -o2 parameter |
|
|
|
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('-v', '--version', type=int, default=3, help='Compose file version (1 or 3)') |
|
parser.add_argument('-o', '--output', type=int, default=0, help='Type of output (0 or 1,2)') |
|
parser.add_argument('cnames', nargs='*', type=str, help='The name of the container to process.') |
|
args = parser.parse_args() |
|
|
|
struct = {} |
|
networks = [] |
|
for cname in args.cnames: |
|
cfile, networks,cmdline = generate(cname) |
|
struct.update(cfile) |
|
|
|
if args.output >0: |
|
print ("\r\n"+ cmdline + "\r\n") |
|
if args.output <2: |
|
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(cname): |
|
c = docker.from_env() |
|
|
|
try: |
|
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 available.") |
|
sys.exit(1) |
|
|
|
cattrs = c.containers.get(cid).attrs |
|
|
|
|
|
# Build yaml dict structure |
|
|
|
cfile = {} |
|
cfile[cattrs['Name'][1:]] = {} |
|
ct = cfile[cattrs['Name'][1:]] |
|
cmdLine ="docker run --name " + str( cattrs['Name'][1:]) |
|
|
|
values = { |
|
'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'] |
|
values['network_mode'] = 'bridge' |
|
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 cattrs['Config']['Cmd'] != None: |
|
values['command'] = " ".join(cattrs['Config']['Cmd']), |
|
|
|
# Check for exposed/bound ports and add them if needed. |
|
try: |
|
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 !=$ |
|
for index, port in enumerate(ports_value): |
|
if port[0] == ':': |
|
ports_value[index] = port[1:] |
|
# print ( "-p " , str (ports_value[index])) |
|
cmdLine = cmdLine + " -p " + str (ports_value[index]) |
|
values['ports'] = ports_value |
|
else: |
|
values['expose'] = expose_value |
|
|
|
except (KeyError, TypeError): |
|
# No ports exposed/bound. Continue without them. |
|
ports = None |
|
|
|
# fix some dates from causing errors. |
|
try: |
|
if values['labels']['org.label-schema.build-date'] != None: |
|
d = values['labels']['org.label-schema.build-date'] |
|
values['labels']['org.label-schema.build-date'] = "'" + str( d ) + "'" |
|
except KeyError as ke: |
|
pass |
|
|
|
# Iterate through values to finish building yaml dict. |
|
for key in values: |
|
value = values[key] |
|
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 |
|
|
|
if cattrs['HostConfig']['Binds']: |
|
for key in cattrs['HostConfig']['Binds']: |
|
cmdLine = cmdLine + ' -v ' + str(key) |
|
|
|
if cattrs['Config']['Env']: |
|
for key in values['environment']: |
|
cmdLine = cmdLine + ' -e ' + str(key.split('=')[0]) |
|
if len(key.split('='))>1: |
|
cmdLine = cmdLine + '="' + str(key.split('=')[1]) + '"' |
|
cmdLine = cmdLine + " " + str ( cattrs['Config']['Image']) |
|
return cfile, networks, cmdLine |
|
|
|
|
|
if __name__ == "__main__": |
|
main() |
|
|
|
|
|
|
|
|
For restoring and tagging the images on the same step, a restore script can be created as follows:
This assumes that
tag
contents look like this:#tag contents docker tag e34e831650c1 ubuntu:latest docker tag f3d89a2abe0d postgres:15
The
restore_images.sh
script will look like:Then run
bash restore_images.sh
.