Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions release/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# 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.10 \
# --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.10
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 LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
ENV DEBIAN_FRONTEND=noninteractive

# Ensure the shell is Bash.
SHELL ["/bin/bash", "-o", "pipefail", "-c"]

# Tell the Dockerfile linter not to warn about how we use apt.
# hadolint global ignore=DL3008,DL3009

RUN apt-get -q update -q && \
apt-get install -y --no-install-recommends ca-certificates \
pkg-config gnupg curl lsb-release git zip unzip

# We avoid the use of "add-apt-repository" because it is only available from the
# "software-properties-common" package, and installing that package brings in a
# lot of other unrelated unnecessary packages. Instead, we fetch the GPG key for
# the deadsnakes package archive and install it where apt can find it.
ENV ID=0xF23C5A6CF475977595C89F51BA6932366A755776
ENV GPG_FILE="/etc/apt/trusted.gpg.d/deadsnakes.gpg"
RUN curl -sSL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=${ID}" | \
gpg --dearmor -o ${GPG_FILE}

ENV PPA_URL="https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu"
ENV APT_FILE="/etc/apt/sources.list.d/deadsnakes.list"
RUN echo "deb [signed-by=${GPG_FILE}] ${PPA_URL} $(lsb_release -cs) main" > "${APT_FILE}"

RUN apt-get -q update -q && \
apt-get install -yq --no-install-recommends make clang g++ zlib1g-dev \
python${PYTHON_VERSION} python${PYTHON_VERSION}-dev \
python${PYTHON_VERSION}-venv 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 && \
update-alternatives --install ${bin}/python3 python3 "${python_path}" 1 && \
update-alternatives --install ${bin}/python3 python3 "${bin}/python${PYTHON_VERSION}" 2

# Install pip, trying ensurepip first and falling back to get-pip.py.
RUN export PIP_BREAK_SYSTEM_PACKAGES=1 PIP_ROOT_USER_ACTION=ignore && \
(python3 -m ensurepip --upgrade --default-pip || \
(curl -sS https://bootstrap.pypa.io/get-pip.py | python3)) && \
python3 -m pip install --no-cache-dir --upgrade 'pip>19'

# Clean up before finishing.
RUN apt-get clean

CMD ["/bin/bash"]
31 changes: 31 additions & 0 deletions release/docker/README.md
Original file line number Diff line number Diff line change
@@ -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 and tutorials in relatively isolated
environments.

The script [`create_docker_images.sh`](create_docker_images.sh) creates separate
images with a range of Python versions 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 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.
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.
68 changes: 68 additions & 0 deletions release/docker/create_docker_images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/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=()

ubuntu_versions+=( "22.04" "24.04" )
python_versions+=( "3.10" "3.11" "3.12" "3.13" )

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"

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."

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}"
# 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}" \
-t ubuntu${os_version%%.*}-cp${py_version//./}:latest .
done
done

echo
echo "~~~~ Done. The following Docker images were created:"
echo
docker images --filter "label=build-datetime=${start_time}"
Loading