in samcli/local/docker/lambda_image.py [0:0]
def _build_image(self, base_image, docker_tag, layers, architecture, stream=None):
"""
Builds the image
Parameters
----------
base_image str
Base Image to use for the new image
docker_tag str
Docker tag (REPOSITORY:TAG) to use when building the image
layers list(samcli.commands.local.lib.provider.Layer)
List of Layers to be use to mount in the image
architecture str
Architecture, either x86_64 or arm64
stream samcli.lib.utils.stream_writer.StreamWriter
Stream to write the build output
Raises
------
samcli.commands.local.cli_common.user_exceptions.ImageBuildException
When docker fails to build the image
"""
dockerfile_content = self._generate_dockerfile(base_image, layers, architecture)
# Create dockerfile in the same directory of the layer cache
dockerfile_name = "dockerfile_" + str(uuid.uuid4())
full_dockerfile_path = Path(self.layer_downloader.layer_cache, dockerfile_name)
stream_writer = stream or StreamWriter(sys.stderr)
try:
with open(str(full_dockerfile_path), "w") as dockerfile:
dockerfile.write(dockerfile_content)
# add dockerfile and rapid source paths
tar_paths = {
str(full_dockerfile_path): "Dockerfile",
self._RAPID_SOURCE_PATH: "/" + get_rapid_name(architecture),
}
for layer in layers:
tar_paths[layer.codeuri] = "/" + layer.name
# Set permission for all the files in the tarball to 500(Read and Execute Only)
# This is need for systems without unix like permission bits(Windows) while creating a unix image
# Without setting this explicitly, tar will default the permission to 666 which gives no execute permission
def set_item_permission(tar_info):
tar_info.mode = 0o500
return tar_info
# Set only on Windows, unix systems will preserve the host permission into the tarball
tar_filter = set_item_permission if platform.system().lower() == "windows" else None
with create_tarball(tar_paths, tar_filter=tar_filter, dereference=True) as tarballfile:
try:
resp_stream = self.docker_client.api.build(
fileobj=tarballfile,
custom_context=True,
rm=True,
tag=docker_tag,
pull=not self.skip_pull_image,
decode=True,
platform=get_docker_platform(architecture),
)
for log in resp_stream:
stream_writer.write_str(".")
stream_writer.flush()
if "error" in log:
stream_writer.write_str(os.linesep)
LOG.exception("Failed to build Docker Image")
raise ImageBuildException("Error building docker image: {}".format(log["error"]))
stream_writer.write_str(os.linesep)
except (docker.errors.BuildError, docker.errors.APIError) as ex:
stream_writer.write_str(os.linesep)
LOG.exception("Failed to build Docker Image")
raise ImageBuildException("Building Image failed.") from ex
finally:
if full_dockerfile_path.exists():
full_dockerfile_path.unlink()