From 5ce1bd361d10d38c5f5e631b49dc9008a21cb501 Mon Sep 17 00:00:00 2001 From: mhucka Date: Fri, 26 Dec 2025 02:30:09 +0000 Subject: [PATCH 1/4] Add scripts for creating docker containers for testing --- release/docker/Dockerfile | 83 ++++++++++++++++++++++++++ release/docker/README.md | 31 ++++++++++ release/docker/create_docker_images.sh | 55 +++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 release/docker/Dockerfile create mode 100644 release/docker/README.md create mode 100755 release/docker/create_docker_images.sh diff --git a/release/docker/Dockerfile b/release/docker/Dockerfile new file mode 100644 index 000000000..bdebd1675 --- /dev/null +++ b/release/docker/Dockerfile @@ -0,0 +1,83 @@ +# Copyright 2025 The TensorFlow Quantum Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================= + +# Summary: build file for making isolated Docker environments for testing. +# This accepts 2 optional build arguments to set the Ubuntu & Python versions. +# Usage example: +# +# docker build --no-cache --build-arg PYTHON_VERSION=3.9 \ +# --build-arg UBUNTU_VERSION=24.04 -t my-image:latest . +# +# Note that the name and tag ("my-image" and "latest" in the example above) are +# yours to choose. They're not set using the arguments or linked to their values. + +# Default values for build arguments: +ARG PYTHON_VERSION=3.9 +ARG UBUNTU_VERSION=22.04 + +FROM ubuntu:${UBUNTU_VERSION} + +# Make the Python version argument visible to the rest of this file after FROM. +ARG PYTHON_VERSION +ENV PYTHON_VERSION=${PYTHON_VERSION} + +ENV TZ=UTC +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 +ENV DEBIAN_FRONTEND=noninteractive + +# Ensure the shell is Bash. +SHELL ["/bin/bash", "-e", "-c"] + +# Tell the Dockerfile linter not to warn about how we use apt. +# hadolint global ignore=DL3008,DL3009 + +# Add the deadsnakes Python package archive to access older Python versions. +RUN apt-get update -q && \ + apt-get install -yq --no-install-recommends software-properties-common \ + gnupg pkg-config git zip unzip zlib1g-dev && \ + add-apt-repository -y ppa:deadsnakes/ppa && \ + apt-get update -q + +# The following conditional is to handle Python 3.12's removal of distutils. +RUN distutils_pkg="python${PYTHON_VERSION}-distutils" && \ + if [[ "${PYTHON_VERSION#*.}" -ge 12 ]]; then \ + distutils_pkg="python3-setuptools"; \ + fi && \ + apt-get install -yq --no-install-recommends python${PYTHON_VERSION} \ + python${PYTHON_VERSION}-dev python${PYTHON_VERSION}-venv ${distutils_pkg} \ + python3-pip python-is-python3 + +# Use update-alternatives to make the desired version be the default. +# hadolint ignore=SC3010 +RUN python_path="" bin="/usr/bin" && \ + case "$(lsb_release -rs)" in \ + "24.04") python_path="${bin}/python3.12" ;; \ + "22.04") python_path="${bin}/python3.10" ;; \ + "20.04") python_path="${bin}/python3.8" ;; \ + *) python_path=$(readlink -f ${bin}/python3) ;; \ + esac && \ + if [[ ! -f "${python_path}" ]]; then \ + echo "ERROR: ${python_path} does not exist." >&2; \ + exit 1; \ + fi && \ + update-alternatives --install ${bin}/python3 python3 "${python_path}" 1 && \ + update-alternatives --install ${bin}/python3 python3 "${bin}/python${PYTHON_VERSION}" 2 + +# Clean up before finishing. +# hadolint ignore=DL3027 +RUN apt clean + +CMD ["/bin/bash"] diff --git a/release/docker/README.md b/release/docker/README.md new file mode 100644 index 000000000..5838cf1d5 --- /dev/null +++ b/release/docker/README.md @@ -0,0 +1,31 @@ +# Docker images for basic testing + +This directory contains a [`Dockerfile`](Dockerfile) for creating Ubuntu +containers with Python installed and very little else compared to the stock +Ubuntu images from https://hub.docker.com/_/ubuntu/. These can be used for +testing TensorFlow Quantum builds in relatively isolated environments. + +The script [`create_docker_images.sh`](create_docker_images.sh) creates +separate images with Python 3.9–3.12 installed in Ubuntu 22.04 and 24.04. +The result is a total of eight images, with names like `ubuntu22-cp39`, +`ubuntu22-cp310`, etc. The script `create_docker_images.sh` is meant to be run +simply like this: + +```shell +./create_docker_images.sh +``` + +The Dockerfile configuration runs a Bash shell as the last step if a container +is not started with any other command to run. When combined with Docker's `-v` +argument, you can easily run commands inside the containere environment while +accessing your TensorFlow Quantum source files. For example: + +```shell +# The next cd command moves to the root of the source tree. +cd $(git rev-parse --show-toplevel) +docker run -it --rm --network host -v .:/tfq ubuntu24-cp312 +``` + +will leave you with a shell prompt inside a basic Ubuntu 24.04 environment with +Python 3.12 preinstalled and your local TensorFlow Quantum source directory +accessible at `/tfq` from inside the container. diff --git a/release/docker/create_docker_images.sh b/release/docker/create_docker_images.sh new file mode 100755 index 000000000..7bfd3ff41 --- /dev/null +++ b/release/docker/create_docker_images.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright 2025 The TensorFlow Quantum Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================= + +# Summary: create a set of Docker images for testing TFQ distributions. +# This loops over a set of Ubuntu versions and Python versions, and builds +# Docker images using the Dockerfile in this directory. +# +# Example of how the resulting images can be run +# docker run -it --rm --network host -v .:/tfq ubuntu22-cp39 + +set -e + +declare -a ubuntu_versions=() +declare -a python_versions=() +declare -a docker_args=() + +ubuntu_versions+=( "22.04" "24.04" ) +python_versions+=( "3.9" "3.10" "3.11" "3.12" ) +total_items=$(( ${#ubuntu_versions[@]} * ${#python_versions[@]})) + +echo "~~~~ Building a total of ${total_items} Docker images" + +# Flag --no-cache forces containers to be rebuilt. +docker_args+=( "--no-cache" ) + +# shellcheck disable=SC2068,SC2145 +for os_version in "${ubuntu_versions[@]}"; do + for py_version in "${python_versions[@]}"; do + echo + echo "~~~~ Python ${py_version} on Ubuntu ${os_version}" + docker build \ + --build-arg PYTHON_VERSION="${py_version}" \ + --build-arg UBUNTU_VERSION="${os_version}" \ + ${docker_args[@]}\ + -t ubuntu${os_version%%.*}-cp${py_version//./}:latest . + done +done + +echo +echo "~~~~ Done. Created the following Docker images:" +echo +docker images --filter "reference=ubuntu*-cp*" From 21bcf7f42ebcfb9ba0cb2a8add602036f58ac11f Mon Sep 17 00:00:00 2001 From: mhucka Date: Fri, 26 Dec 2025 22:58:50 +0000 Subject: [PATCH 2/4] Remove installation of distutils/setuptools Installing those can hide the problem that these are not available in newer Python versions, giving a false sense of security to a developer. --- release/docker/Dockerfile | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/release/docker/Dockerfile b/release/docker/Dockerfile index bdebd1675..425828e01 100644 --- a/release/docker/Dockerfile +++ b/release/docker/Dockerfile @@ -51,14 +51,9 @@ RUN apt-get update -q && \ add-apt-repository -y ppa:deadsnakes/ppa && \ apt-get update -q -# The following conditional is to handle Python 3.12's removal of distutils. -RUN distutils_pkg="python${PYTHON_VERSION}-distutils" && \ - if [[ "${PYTHON_VERSION#*.}" -ge 12 ]]; then \ - distutils_pkg="python3-setuptools"; \ - fi && \ - apt-get install -yq --no-install-recommends python${PYTHON_VERSION} \ - python${PYTHON_VERSION}-dev python${PYTHON_VERSION}-venv ${distutils_pkg} \ - python3-pip python-is-python3 +RUN apt-get install -yq --no-install-recommends python${PYTHON_VERSION} \ + python${PYTHON_VERSION}-dev python${PYTHON_VERSION}-venv python3-pip \ + python-is-python3 # Use update-alternatives to make the desired version be the default. # hadolint ignore=SC3010 @@ -69,10 +64,6 @@ RUN python_path="" bin="/usr/bin" && \ "20.04") python_path="${bin}/python3.8" ;; \ *) python_path=$(readlink -f ${bin}/python3) ;; \ esac && \ - if [[ ! -f "${python_path}" ]]; then \ - echo "ERROR: ${python_path} does not exist." >&2; \ - exit 1; \ - fi && \ update-alternatives --install ${bin}/python3 python3 "${python_path}" 1 && \ update-alternatives --install ${bin}/python3 python3 "${bin}/python${PYTHON_VERSION}" 2 From 816dc387b31891edd0b8c666f6090eefbf91a43b Mon Sep 17 00:00:00 2001 From: mhucka Date: Sat, 27 Dec 2025 21:55:40 +0000 Subject: [PATCH 3/4] Fix a typo and remove an overly-specific statement --- release/docker/README.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/release/docker/README.md b/release/docker/README.md index 5838cf1d5..0db235656 100644 --- a/release/docker/README.md +++ b/release/docker/README.md @@ -3,22 +3,23 @@ This directory contains a [`Dockerfile`](Dockerfile) for creating Ubuntu containers with Python installed and very little else compared to the stock Ubuntu images from https://hub.docker.com/_/ubuntu/. These can be used for -testing TensorFlow Quantum builds in relatively isolated environments. +testing TensorFlow Quantum builds and tutorials in relatively isolated +environments. -The script [`create_docker_images.sh`](create_docker_images.sh) creates -separate images with Python 3.9–3.12 installed in Ubuntu 22.04 and 24.04. -The result is a total of eight images, with names like `ubuntu22-cp39`, -`ubuntu22-cp310`, etc. The script `create_docker_images.sh` is meant to be run -simply like this: +The script [`create_docker_images.sh`](create_docker_images.sh) creates separate +images with a range of Python versions (currently 3.9–3.12) installed in +Ubuntu 22.04 and 24.04. The result is a set of images with names like +`ubuntu22-cp39`, `ubuntu22-cp310`, etc. The script `create_docker_images.sh` is +meant to be run simply like this: ```shell ./create_docker_images.sh ``` -The Dockerfile configuration runs a Bash shell as the last step if a container -is not started with any other command to run. When combined with Docker's `-v` -argument, you can easily run commands inside the containere environment while -accessing your TensorFlow Quantum source files. For example: +The configuration in `Dockerfile` runs a Bash shell as the last step if a +container is not started with any other command to run. When combined with +Docker's `-v` argument, you can easily run commands inside the container +environment while accessing your TensorFlow Quantum source files. For example: ```shell # The next cd command moves to the root of the source tree. From 6e297d2b0609bb49352246ab180618858f6e5d69 Mon Sep 17 00:00:00 2001 From: mhucka Date: Sat, 27 Dec 2025 22:46:47 +0000 Subject: [PATCH 4/4] Improve create_docker_images.sh Changes: * Add support for a verbose flag and a help flag * Use a better way to list the images built by this script --- release/docker/create_docker_images.sh | 33 ++++++++++++++++++-------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/release/docker/create_docker_images.sh b/release/docker/create_docker_images.sh index 7bfd3ff41..76022042d 100755 --- a/release/docker/create_docker_images.sh +++ b/release/docker/create_docker_images.sh @@ -25,31 +25,44 @@ set -e declare -a ubuntu_versions=() declare -a python_versions=() -declare -a docker_args=() ubuntu_versions+=( "22.04" "24.04" ) python_versions+=( "3.9" "3.10" "3.11" "3.12" ) -total_items=$(( ${#ubuntu_versions[@]} * ${#python_versions[@]})) -echo "~~~~ Building a total of ${total_items} Docker images" +usage="Usage: ${0} [OPTIONS] + +Build a set of basic Ubuntu Linux x86_64 Docker images with +Python preinstalled. + +General options: + -h Show this help message and exit + -v Run Docker build with verbose progress output" -# Flag --no-cache forces containers to be rebuilt. -docker_args+=( "--no-cache" ) +while getopts "hv" opt; do + case "${opt}" in + h) echo "${usage}"; exit 0 ;; + v) export BUILDKIT_PROGRESS=plain ;; + ?) echo "${usage}"; exit 1 ;; + esac +done + +total_items=$(( ${#ubuntu_versions[@]} * ${#python_versions[@]})) +echo "Building a total of ${total_items} Docker images." -# shellcheck disable=SC2068,SC2145 +start_time="$(date +"%Y-%m-%d-%H%M")" for os_version in "${ubuntu_versions[@]}"; do for py_version in "${python_versions[@]}"; do echo echo "~~~~ Python ${py_version} on Ubuntu ${os_version}" - docker build \ + # shellcheck disable=SC2086 # Lack of quotes around vars is ok here. + docker build --no-cache --label "build-datetime=${start_time}" \ --build-arg PYTHON_VERSION="${py_version}" \ --build-arg UBUNTU_VERSION="${os_version}" \ - ${docker_args[@]}\ -t ubuntu${os_version%%.*}-cp${py_version//./}:latest . done done echo -echo "~~~~ Done. Created the following Docker images:" +echo "~~~~ Done. The following Docker images were created:" echo -docker images --filter "reference=ubuntu*-cp*" +docker images --filter "label=build-datetime=${start_time}"