Created
October 17, 2018 06:10
-
-
Save tzickel/2111dd013d1c4f8c765a538e74646f95 to your computer and use it in GitHub Desktop.
A simple docker build extension that works with .gitignore file directives and you can specify both Dockerfile and multiple .gitignore paths
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Version 0.0.1 (works with python2.7 and python3) | |
# Does not work with non-local context (i.e. git, remote archives) | |
# You need the pathspec package installed (pip install pathspec) | |
# Pass any docker build arguments you want to use after -- argument (i.e., dockerignore.py . -- -t blah) | |
# This works with .gitignore syntax, not .dockerignore ( https://git-scm.com/docs/gitignore#_pattern_format ) | |
import tarfile | |
import subprocess | |
import argparse | |
import os | |
import sys | |
try: | |
from StringIO import StringIO | |
except ModuleNotFoundError: | |
from io import BytesIO as StringIO | |
import pathspec | |
def tar_add_string_as_file(tar, name, s): | |
t = tarfile.TarInfo(name=name) | |
t.size = len(s) | |
tar.addfile(tarinfo=t, fileobj=StringIO(s)) | |
def build_from(dockerfile, context, gitignorefiles, compress, buildparams, verbose): | |
def filter(tarinfo): | |
if not dockerfile and tarinfo.name == 'Dockerfile': | |
return tarinfo | |
for ps in pathspecs: | |
if ps.match_file(tarinfo.name): | |
return | |
if verbose: | |
print(tarinfo.name) | |
return tarinfo | |
if not gitignorefiles: | |
gitignorefiles = [] | |
if not os.path.isdir(context): | |
raise Exception('context must be a directory: %s' % context) | |
pathspecs = [] | |
for filepath in gitignorefiles: | |
with open(filepath, 'rt') as f: | |
spec = pathspec.PathSpec.from_lines('gitignore', f) | |
pathspecs.append(spec) | |
proc = subprocess.Popen(['docker', 'build', '-'] + buildparams, stdin=subprocess.PIPE) | |
try: | |
with tarfile.open(mode='w|' + compress, fileobj=proc.stdin) as tar: | |
tar_add_string_as_file(tar, '.dockerignore', b'Dockerfile\n.dockerignore') | |
tar.add(context, arcname='', filter=filter) | |
if dockerfile: | |
tar.add(dockerfile, arcname='Dockerfile') | |
proc.stdin.close() | |
return proc.wait() | |
except Exception: | |
proc.kill() | |
raise | |
def fix_argv(): | |
try: | |
ind = sys.argv.index('--') | |
ret = sys.argv[ind+1:] | |
sys.argv = sys.argv[:ind] | |
return ret | |
except ValueError: | |
return [] | |
if __name__ == '__main__': | |
docker_build_args = fix_argv() | |
parser = argparse.ArgumentParser() | |
parser.add_argument("context") | |
parser.add_argument("-f", "--file", help="Name of the Dockerfile (Default is 'PATH/Dockerfile')") | |
parser.add_argument("-i", "--gitignorefiles", action="append", help="a .gitignore file") | |
parser.add_argument("--gz", action="store_true", help="Compress the build context using gzip") | |
parser.add_argument("--bz2", action="store_true", help="Compress the build context using bzip2") | |
parser.add_argument("--verbose", action="store_true", help="Show the files added to the context") | |
args = parser.parse_args() | |
if args.gz and args.bz2: | |
raise Exception('Cannot enable both gzip and bzip2 compression') | |
compress = 'gz' if args.gz else 'bz2' if args.bz2 else '' | |
sys.exit(build_from(args.file, args.context, args.gitignorefiles, compress, docker_build_args, args.verbose)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment