Skip to content

Commit

Permalink
Support env expansion and pre/post build scripts (#17)
Browse files Browse the repository at this point in the history
* Initial changes to dockerutils to support env expansion and also pre/post build scripts

* Fixed a couple of little items in the build-image command

* Added the changes requested on the PR
  • Loading branch information
mikekwright authored and rappdw committed Oct 8, 2018
1 parent 312afb1 commit 12ed489
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 5 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ build
activate
.coverage
.pytest_cache
.venv
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ docker directory tree. Each of these sections may contain one of the following:
* `pull_FROM_on_force` - defaults to False, if True, add --pull to build command when force building image (or base image)
* `image_repo` - the repository to publish the image to
* `publication_tag` - the tag for publication (full image name + tag)
* `pre_build_script` - A shell command or script to run before a docker build is issued
* `post_build_script` - A shell command or script to run after a docker build has been compeleted (successfully)

### Synthetic Images
Additionally, "synthetic" images can be specified by adding a `run-image` section with a `synthetic_images` definition
Expand All @@ -102,14 +104,19 @@ tag=experiment.2017.12.16
...
```
### Volume Replacement Variables
The volume specification may contain replacement variable designations of the form `{var}`. The supported variables
include:

The volume specification may contain either environment variables (`$name` and `${name}` formats) as well as specific
variable replacement designations of the form `{var}`. The supported variables include:

* `project_root` - will be replaced with the root directory name of the project
* `user` - will be replaced with the user name of the user running the command
* `project` - replace with project namge

### Image Push Replacement Variables

The `publication_tag` may contain either environment variables (`$name` and `${name}` formats) as well as specific
variable replacement designations of the form `{var}`. The supported variables include:

* `account` - AWS account designation
* `region` - AWS region
* `image` - Image name
Expand Down
35 changes: 32 additions & 3 deletions scripts/build-image
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,26 @@ def is_multistage(mode):
return 'as builder' in open(f'docker/{mode}/Dockerfile').read()


def build(image, image_name, image_tag, pull=False):
def run_pre_script(script: str, config: dict) -> int:
print(f'Running pre-build-script: "{script}"')
return subprocess.call(shlex.split(script), cwd=os.getcwd())


def run_post_script(script: str, config: dict) -> int:
print(f'Running post-build-script: "{script}"')
return subprocess.call(shlex.split(script), cwd=os.getcwd())


def build(image, image_name, image_tag, config={}, pull=False):
pre_script = config.get('pre_build_script', None)
post_script = config.get('post_build_script', None)

if pre_script:
rc = run_pre_script(pre_script, config=config)
if rc != 0:
print(f'pre-build-script failed: {rc}')
return rc

rc = 0
pull_base = ''
if pull:
Expand All @@ -30,6 +49,14 @@ def build(image, image_name, image_tag, pull=False):
if not rc:
rc = image_operation(f'docker build {pull_base} --compress -t {image_name}:{image_tag} '
f'-f docker/{image}/Dockerfile .')

if rc != 0:
print(f'docker build failed: {rc}')
return rc

if post_script:
rc = run_post_script(post_script, config=config)

return rc


Expand Down Expand Up @@ -92,11 +119,13 @@ if __name__ == '__main__':
image_tag = args.image_tag

pull_FROM_on_force = False
image_config = {}
if image in config.sections():
if 'pull_FROM_on_force' in config[image]:
image_config = config[image]
if 'pull_FROM_on_force' in image_config:
pull_FROM_on_force = config[image]['pull_FROM_on_force']

rc = fn(image, image_name, image_tag, args.pull_base or (args.force_build_base and pull_FROM_on_force))
rc = fn(image, image_name, image_tag, config=image_config, pull=args.pull_base or (args.force_build_base and pull_FROM_on_force))
# because an image may not be present on the clean, ignore a non-zero return code
if rc and not args.image == 'clean':
sys.exit(rc)
Expand Down
2 changes: 2 additions & 0 deletions scripts/publish-image
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ if __name__ == '__main__':
tag=image_tag,
user=getpass.getuser()
)
publication_tag = os.path.expandvars(publication_tag)
ecr_client = boto3.client('ecr')
auth_data = ecr_client.get_authorization_token()
user, password = base64.b64decode(auth_data['authorizationData'][0]['authorizationToken']).decode().split(
Expand All @@ -103,6 +104,7 @@ if __name__ == '__main__':
tag=image_tag,
user=getpass.getuser()
)
publication_tag = os.path.expandvars(publication_tag)
# TODO: should we pick up user and password for docker.com? Maybe via credstash?
rc = docker_login_dockerhub()

Expand Down
2 changes: 2 additions & 0 deletions scripts/run-image
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ def run(mode, image_name, image_tag, **kwargs):
user=user,
project=os.path.split(get_root_dir())[1]
)
volumes = os.path.expandvars(volumes)

if kwargs['network']:
kwargs['network'] = f"--network {kwargs['network']}"

Expand Down

0 comments on commit 12ed489

Please sign in to comment.