Skip to content

Commit

Permalink
feat: Support additional arguments for docker and entrypoint override (
Browse files Browse the repository at this point in the history
…#366)

Co-authored-by: Anton Babenko <[email protected]>
  • Loading branch information
AllanBenson001 and antonbabenko authored Oct 31, 2022
1 parent 61180bd commit dc4d000
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 9 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,27 @@ Note that by default, the `docker_image` used comes from the registry `public.ec

If you override `docker_image`, be sure to keep the image in sync with your `runtime`. During the plan phase, when using docker, there is no check that the `runtime` is available to build the package. That means that if you use an image that does not have the runtime, the plan will still succeed, but then the apply will fail.

#### Passing additional Docker options

To add flexibility when building in docker, you can pass any number of additional options that you require (see [Docker run reference](https://docs.docker.com/engine/reference/run/) for available options):

```hcl
docker_additional_options = [
"-e", "MY_ENV_VAR='My environment variable value'",
"-v", "/local:/docker-vol",
]
```

#### Overriding Docker Entrypoint

To override the docker entrypoint when building in docker, set `docker_entrypoint`:

```hcl
docker_entrypoint = "/entrypoint/entrypoint.sh"
```

The entrypoint must map to a path within your container, so you need to either build your own image that contains the entrypoint or map it to a file on the host by mounting a volume (see [Passing additional Docker options](#passing-additional-docker-options)).

## <a name="package"></a> Deployment package - Create or use existing

By default, this module creates deployment package and uses it to create or update Lambda Function or Lambda Layer.
Expand Down Expand Up @@ -716,7 +737,9 @@ No modules.
| <a name="input_description"></a> [description](#input\_description) | Description of your Lambda Function (or Layer) | `string` | `""` | no |
| <a name="input_destination_on_failure"></a> [destination\_on\_failure](#input\_destination\_on\_failure) | Amazon Resource Name (ARN) of the destination resource for failed asynchronous invocations | `string` | `null` | no |
| <a name="input_destination_on_success"></a> [destination\_on\_success](#input\_destination\_on\_success) | Amazon Resource Name (ARN) of the destination resource for successful asynchronous invocations | `string` | `null` | no |
| <a name="input_docker_additional_options"></a> [docker\_additional\_options](#input\_docker\_additional\_options) | Additional options to pass to the docker run command (e.g. to set environment variables, volumes, etc.) | `list(string)` | `[]` | no |
| <a name="input_docker_build_root"></a> [docker\_build\_root](#input\_docker\_build\_root) | Root dir where to build in Docker | `string` | `""` | no |
| <a name="input_docker_entrypoint"></a> [docker\_entrypoint](#input\_docker\_entrypoint) | Path to the Docker entrypoint to use | `string` | `null` | no |
| <a name="input_docker_file"></a> [docker\_file](#input\_docker\_file) | Path to a Dockerfile when building in Docker | `string` | `""` | no |
| <a name="input_docker_image"></a> [docker\_image](#input\_docker\_image) | Docker image to use for the build | `string` | `""` | no |
| <a name="input_docker_pip_cache"></a> [docker\_pip\_cache](#input\_docker\_pip\_cache) | Whether to mount a shared pip cache folder into docker environment or not | `any` | `null` | no |
Expand Down
1 change: 1 addition & 0 deletions examples/build-package/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Note that this example may create resources which cost money. Run `terraform des
| <a name="module_package_with_npm_requirements_in_docker"></a> [package\_with\_npm\_requirements\_in\_docker](#module\_package\_with\_npm\_requirements\_in\_docker) | ../../ | n/a |
| <a name="module_package_with_patterns"></a> [package\_with\_patterns](#module\_package\_with\_patterns) | ../../ | n/a |
| <a name="module_package_with_pip_requirements_in_docker"></a> [package\_with\_pip\_requirements\_in\_docker](#module\_package\_with\_pip\_requirements\_in\_docker) | ../../ | n/a |
| <a name="module_package_with_pip_requirements_in_docker_overriding_entrypoint"></a> [package\_with\_pip\_requirements\_in\_docker\_overriding\_entrypoint](#module\_package\_with\_pip\_requirements\_in\_docker\_overriding\_entrypoint) | ../../ | n/a |

## Resources

Expand Down
29 changes: 29 additions & 0 deletions examples/build-package/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,35 @@ module "package_with_pip_requirements_in_docker" {
build_in_docker = true
}

# Create zip-archive which contains:
# 1. A single file - index.py
# 2. Content of directory "dir2"
# 3. Install pip requirements
# "pip install" is running in a Docker container for the specified runtime
# The docker entrypoint is overridden, allowing you to run additional commands within the container
module "package_with_pip_requirements_in_docker_overriding_entrypoint" {
source = "../../"

create_function = false

runtime = "python3.8"
source_path = [
"${path.module}/../fixtures/python3.8-app1/index.py",
"${path.module}/../fixtures/python3.8-app1/dir1/dir2",
{
pip_requirements = "${path.module}/../fixtures/python3.8-app1/requirements.txt"
}
]
hash_extra = "package_with_pip_requirements_in_docker_overriding_entrypoint"

build_in_docker = true
docker_additional_options = [
"-e", "MY_ENV_VAR='My environment variable value'",
"-v", "${abspath(path.module)}/../fixtures/python3.8-app1/docker/entrypoint.sh:/entrypoint/entrypoint.sh:ro",
]
docker_entrypoint = "/entrypoint/entrypoint.sh"
}

# Create zip-archive which contains content of directory with commands and patterns applied.
#
# Notes:
Expand Down
11 changes: 11 additions & 0 deletions examples/fixtures/python3.8-app1/docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/sh
set -e

echo in entrypoint
echo I can read $MY_ENV_VAR and my volume:
ls -la /entrypoint

echo "running command $@"
"$@"

echo finished running entrypoint
16 changes: 12 additions & 4 deletions package.py
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,7 @@ def install_pip_requirements(query, requirements_file, tmp_dir):
'.', shell_command, runtime,
image=docker_image_tag_id,
shell=True, ssh_agent=with_ssh_agent,
pip_cache_dir=pip_cache_dir,
pip_cache_dir=pip_cache_dir, docker=docker,
))
else:
cmd_log.info(shlex_join(pip_command))
Expand Down Expand Up @@ -1260,7 +1260,8 @@ def install_npm_requirements(query, requirements_file, tmp_dir):
check_call(docker_run_command(
'.', shell_command, runtime,
image=docker_image_tag_id,
shell=True, ssh_agent=with_ssh_agent
shell=True, ssh_agent=with_ssh_agent,
docker=docker,
))
else:
cmd_log.info(shlex_join(npm_command))
Expand Down Expand Up @@ -1310,7 +1311,8 @@ def docker_build_command(tag=None, docker_file=None, build_root=False):

def docker_run_command(build_root, command, runtime,
image=None, shell=None, ssh_agent=False,
interactive=False, pip_cache_dir=None, poetry_cache_dir=None):
interactive=False, pip_cache_dir=None, poetry_cache_dir=None,
docker=None):
""""""
if platform.system() not in ('Linux', 'Darwin'):
raise RuntimeError("Unsupported platform for docker building")
Expand All @@ -1331,6 +1333,9 @@ def docker_run_command(build_root, command, runtime,
'-v', '{}/.ssh/known_hosts:/root/.ssh/known_hosts:z'.format(home),
])

if docker and docker.docker_additional_options:
docker_cmd.extend(docker.docker_additional_options)

if ssh_agent:
if platform.system() == 'Darwin':
# https://docs.docker.com/docker-for-mac/osxfs/#ssh-agent-forwarding
Expand Down Expand Up @@ -1362,7 +1367,10 @@ def docker_run_command(build_root, command, runtime,
if not image:
image = 'public.ecr.aws/sam/build-{}'.format(runtime)

docker_cmd.extend(['--entrypoint', ''])
if docker and docker.docker_entrypoint:
docker_cmd.extend(['--entrypoint', docker.docker_entrypoint])
else:
docker_cmd.extend(['--entrypoint', ''])

docker_cmd.append(image)

Expand Down
12 changes: 7 additions & 5 deletions package.tf
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ data "external" "archive_prepare" {
})

docker = var.build_in_docker ? jsonencode({
docker_pip_cache = var.docker_pip_cache
docker_build_root = var.docker_build_root
docker_file = var.docker_file
docker_image = var.docker_image
with_ssh_agent = var.docker_with_ssh_agent
docker_pip_cache = var.docker_pip_cache
docker_build_root = var.docker_build_root
docker_file = var.docker_file
docker_image = var.docker_image
with_ssh_agent = var.docker_with_ssh_agent
docker_additional_options = var.docker_additional_options
docker_entrypoint = var.docker_entrypoint
}) : null

artifacts_dir = var.artifacts_dir
Expand Down
12 changes: 12 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,18 @@ variable "docker_pip_cache" {
default = null
}

variable "docker_additional_options" {
description = "Additional options to pass to the docker run command (e.g. to set environment variables, volumes, etc.)"
type = list(string)
default = []
}

variable "docker_entrypoint" {
description = "Path to the Docker entrypoint to use"
type = string
default = null
}

variable "recreate_missing_package" {
description = "Whether to recreate missing Lambda package if it is missing locally or not"
type = bool
Expand Down

0 comments on commit dc4d000

Please sign in to comment.