in samcli/lib/build/app_builder.py [0:0]
def _build_lambda_image(self, function_name: str, metadata: Dict, architecture: str) -> str:
"""
Build an Lambda image
Parameters
----------
function_name str
Name of the function (logical id or function name)
metadata dict
Dictionary representing the Metadata attached to the Resource in the template
architecture : str
The architecture type 'x86_64' and 'arm64' in AWS
Returns
-------
str
The full tag (org/repo:tag) of the image that was built
"""
LOG.info("Building image for %s function", function_name)
dockerfile = cast(str, metadata.get("Dockerfile"))
docker_context = cast(str, metadata.get("DockerContext"))
# Have a default tag if not present.
tag = metadata.get("DockerTag", "latest")
docker_tag = f"{function_name.lower()}:{tag}"
docker_build_target = metadata.get("DockerBuildTarget", None)
docker_build_args = metadata.get("DockerBuildArgs", {})
if not dockerfile or not docker_context:
raise DockerBuildFailed("Docker file or Docker context metadata are missed.")
if not isinstance(docker_build_args, dict):
raise DockerBuildFailed("DockerBuildArgs needs to be a dictionary!")
docker_context_dir = pathlib.Path(self._base_dir, docker_context).resolve()
if not is_docker_reachable(self._docker_client):
raise DockerConnectionError(msg=f"Building image for {function_name} requires Docker. is Docker running?")
if os.environ.get("SAM_BUILD_MODE") and isinstance(docker_build_args, dict):
docker_build_args["SAM_BUILD_MODE"] = os.environ.get("SAM_BUILD_MODE")
docker_tag = "-".join([docker_tag, docker_build_args["SAM_BUILD_MODE"]])
if isinstance(docker_build_args, dict):
LOG.info("Setting DockerBuildArgs for %s function", function_name)
build_args = {
"path": str(docker_context_dir),
"dockerfile": str(pathlib.Path(dockerfile).as_posix()),
"tag": docker_tag,
"buildargs": docker_build_args,
"platform": get_docker_platform(architecture),
"rm": True,
}
if docker_build_target:
build_args["target"] = cast(str, docker_build_target)
try:
(build_image, build_logs) = self._docker_client.images.build(**build_args)
LOG.debug("%s image is built for %s function", build_image, function_name)
except docker.errors.BuildError as ex:
LOG.error("Failed building function %s", function_name)
self._stream_lambda_image_build_logs(ex.build_log, function_name, False)
raise DockerBuildFailed(str(ex)) from ex
# The Docker-py low level api will stream logs back but if an exception is raised by the api
# this is raised when accessing the generator. So we need to wrap accessing build_logs in a try: except.
try:
self._stream_lambda_image_build_logs(build_logs, function_name)
except docker.errors.APIError as e:
if e.is_server_error and "Cannot locate specified Dockerfile" in e.explanation:
raise DockerfileOutSideOfContext(e.explanation) from e
# Not sure what else can be raise that we should be catching but re-raising for now
raise
return docker_tag