From 06543dd7267d0cf047a2cfd48b0f26170eebaaf2 Mon Sep 17 00:00:00 2001 From: Ben Potter Date: Fri, 4 Jul 2025 17:35:54 +0000 Subject: [PATCH 1/3] feat: rename enterprise-* images to example-* while maintaining backward compatibility --- README.md | 19 ++++-- scripts/build_images.sh | 6 +- scripts/push_images.sh | 17 +++-- scripts/scan_images.sh | 139 ++++++++++++++++++++++++++-------------- 4 files changed, 122 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index ff2d5b91..429d817f 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,27 @@ -# Enterprise Example Images +# Coder Example Images This repository contains example images for use with [Coder](https://coder.com/docs/v2/latest). -- `enterprise-base`: Contains an example image that can be used as a base for +- `example-base`: Contains an example image that can be used as a base for other images. -- `enterprise-minimal`: Contains a minimal image that contains only the required +- `example-minimal`: Contains a minimal image that contains only the required utilities for a Coder workspace to bootstrap successfully. +- `example-golang`: Contains Go development tools. +- `example-java`: Contains Java development tools. +- `example-node`: Contains Node.js development tools. +- `example-desktop`: Contains a desktop environment accessible via web browser. ## Images on Docker Hub -Each of these images is also published to Docker Hub under the -`codercom/enterprise-[name]` repository. For example, `base` is available at -https://hub.docker.com/r/codercom/enterprise-base. The tag is taken from the +Each of these images is published to Docker Hub under the +`codercom/example-[name]` repository. For example, `base` is available at +https://hub.docker.com/r/codercom/example-base. The tag is taken from the filename of the Dockerfile. For example, `base/ubuntu.Dockerfile` is under the `ubuntu` tag. +> For backward compatibility, these images are also available with the `enterprise-` prefix +> (e.g., `codercom/enterprise-base`), but the `example-` prefix is recommended for new deployments. + ## Contributing See our [contributing guide](.github/CONTRIBUTING.md). diff --git a/scripts/build_images.sh b/scripts/build_images.sh index 2033375f..d01ded39 100755 --- a/scripts/build_images.sh +++ b/scripts/build_images.sh @@ -91,7 +91,8 @@ fi for image in "${IMAGES[@]}"; do image_dir="$PROJECT_ROOT/images/$image" image_file="${TAG}.Dockerfile" - image_ref="codercom/enterprise-$image:$TAG" + enterprise_image_ref="codercom/enterprise-$image:$TAG" + example_image_ref="codercom/example-$image:$TAG" image_path="$image_dir/$image_file" if [ ! -f "$image_path" ]; then @@ -105,5 +106,6 @@ for image in "${IMAGES[@]}"; do "${docker_flags[@]}" \ "$image_dir" \ --file="$image_path" \ - --tag="$image_ref" \| indent + --tag="$example_image_ref" \ + --tag="$enterprise_image_ref" \| indent done diff --git a/scripts/push_images.sh b/scripts/push_images.sh index 4046dcb1..5eed22a8 100755 --- a/scripts/push_images.sh +++ b/scripts/push_images.sh @@ -92,8 +92,10 @@ date_str=$(date --utc +%Y%m%d) for image in "${IMAGES[@]}"; do image_dir="$PROJECT_ROOT/images/$image" image_file="${TAG}.Dockerfile" - image_ref="codercom/enterprise-$image:$TAG" - image_ref_date="${image_ref}-${date_str}" + enterprise_image_ref="codercom/enterprise-$image:$TAG" + enterprise_image_ref_date="${enterprise_image_ref}-${date_str}" + example_image_ref="codercom/example-$image:$TAG" + example_image_ref_date="${example_image_ref}-${date_str}" image_path="$image_dir/$image_file" if [ ! -f "$image_path" ]; then @@ -104,7 +106,14 @@ for image in "${IMAGES[@]}"; do fi build_id=$(cat "build_${image}.json" | jq -r .\[\"depot.build\"\].buildID) - run_trace $DRY_RUN depot push --project "gb3p8xrshk" --tag "$image_ref" "$build_id" - run_trace $DRY_RUN depot push --project "gb3p8xrshk" --tag "$image_ref_date" "$build_id" + + # Push example images (primary) + run_trace $DRY_RUN depot push --project "gb3p8xrshk" --tag "$example_image_ref" "$build_id" + run_trace $DRY_RUN depot push --project "gb3p8xrshk" --tag "$example_image_ref_date" "$build_id" + run_trace $DRY_RUN depot push --project "gb3p8xrshk" --tag "codercom/example-${image}:latest" "$build_id" + + # Push enterprise images (alias) + run_trace $DRY_RUN depot push --project "gb3p8xrshk" --tag "$enterprise_image_ref" "$build_id" + run_trace $DRY_RUN depot push --project "gb3p8xrshk" --tag "$enterprise_image_ref_date" "$build_id" run_trace $DRY_RUN depot push --project "gb3p8xrshk" --tag "codercom/enterprise-${image}:latest" "$build_id" done diff --git a/scripts/scan_images.sh b/scripts/scan_images.sh index c9c74127..33a83e9c 100755 --- a/scripts/scan_images.sh +++ b/scripts/scan_images.sh @@ -103,58 +103,103 @@ trivy_tmp_dir="$(mktemp -d -p "$PROJECT_ROOT")" trap 'rm -rf "$tmp_dir" "$trivy_tmp_dir"' EXIT +# Scan both example and enterprise images for image in "${IMAGES[@]}"; do - image_ref="codercom/enterprise-${image}:${TAG}" - image_name="${image}-${TAG}" - output="${tmp_dir}/${image}-${TAG}.sarif" - - if ! docker image inspect "$image_ref" >/dev/null 2>&1; then - echo "Image '$image_ref' does not exist locally; skipping" >&2 - continue - fi - - old_tmpdir="${TMPDIR:-}" - export TMPDIR="$trivy_tmp_dir" - - # The timeout is set to 15 minutes because in Java images it can take a while - # to scan JAR files for vulnerabilities. - run_trace $DRY_RUN trivy image \ - --severity CRITICAL,HIGH \ - --format sarif \ - --output "$output" \ - --timeout 15m0s \ - "$image_ref" 2>&1 | indent - - if [ "$old_tmpdir" = "" ]; then - unset TMPDIR + # Process example images (primary) + example_image_ref="codercom/example-${image}:${TAG}" + example_image_name="example-${image}-${TAG}" + example_output="${tmp_dir}/example-${image}-${TAG}.sarif" + + if docker image inspect "$example_image_ref" >/dev/null 2>&1; then + old_tmpdir="${TMPDIR:-}" + export TMPDIR="$trivy_tmp_dir" + + # The timeout is set to 15 minutes because in Java images it can take a while + # to scan JAR files for vulnerabilities. + run_trace $DRY_RUN trivy image \ + --severity CRITICAL,HIGH \ + --format sarif \ + --output "$example_output" \ + --timeout 15m0s \ + "$example_image_ref" 2>&1 | indent + + if [ "$old_tmpdir" = "" ]; then + unset TMPDIR + else + export TMPDIR="$old_tmpdir" + fi + + if [ $DRY_RUN = false ] && [ -f "$example_output" ]; then + # Do substitutions to add extra details to every message. Without these + # substitutions, most messages won't have any information about which image + # the vulnerability was found in. + jq \ + ".runs[].tool.driver.name |= \"Trivy ${example_image_name}\"" \ + "$example_output" >"$example_output.tmp" + mv "$example_output.tmp" "$example_output" + jq \ + ".runs[].results[].locations[].physicalLocation.artifactLocation.uri |= \"${example_image_name}/\" + ." \ + "$example_output" >"$example_output.tmp" + mv "$example_output.tmp" "$example_output" + jq \ + ".runs[].results[].locations[].message.text |= \"${example_image_name}: \" + ." \ + "$example_output" >"$example_output.tmp" + mv "$example_output.tmp" "$example_output" + elif [ $DRY_RUN = false ]; then + echo "No SARIF output found for image '$example_image_ref' at '$example_output'" >&2 + exit 1 + fi else - export TMPDIR="$old_tmpdir" + echo "Image '$example_image_ref' does not exist locally; skipping" >&2 fi - if [ $DRY_RUN = true ]; then - continue - fi - - if [ ! -f "$output" ]; then - echo "No SARIF output found for image '$image_ref' at '$output'" >&2 - exit 1 + # Process enterprise images (alias) + enterprise_image_ref="codercom/enterprise-${image}:${TAG}" + enterprise_image_name="enterprise-${image}-${TAG}" + enterprise_output="${tmp_dir}/enterprise-${image}-${TAG}.sarif" + + if docker image inspect "$enterprise_image_ref" >/dev/null 2>&1; then + old_tmpdir="${TMPDIR:-}" + export TMPDIR="$trivy_tmp_dir" + + # The timeout is set to 15 minutes because in Java images it can take a while + # to scan JAR files for vulnerabilities. + run_trace $DRY_RUN trivy image \ + --severity CRITICAL,HIGH \ + --format sarif \ + --output "$enterprise_output" \ + --timeout 15m0s \ + "$enterprise_image_ref" 2>&1 | indent + + if [ "$old_tmpdir" = "" ]; then + unset TMPDIR + else + export TMPDIR="$old_tmpdir" + fi + + if [ $DRY_RUN = false ] && [ -f "$enterprise_output" ]; then + # Do substitutions to add extra details to every message. Without these + # substitutions, most messages won't have any information about which image + # the vulnerability was found in. + jq \ + ".runs[].tool.driver.name |= \"Trivy ${enterprise_image_name}\"" \ + "$enterprise_output" >"$enterprise_output.tmp" + mv "$enterprise_output.tmp" "$enterprise_output" + jq \ + ".runs[].results[].locations[].physicalLocation.artifactLocation.uri |= \"${enterprise_image_name}/\" + ." \ + "$enterprise_output" >"$enterprise_output.tmp" + mv "$enterprise_output.tmp" "$enterprise_output" + jq \ + ".runs[].results[].locations[].message.text |= \"${enterprise_image_name}: \" + ." \ + "$enterprise_output" >"$enterprise_output.tmp" + mv "$enterprise_output.tmp" "$enterprise_output" + elif [ $DRY_RUN = false ]; then + echo "No SARIF output found for image '$enterprise_image_ref' at '$enterprise_output'" >&2 + exit 1 + fi + else + echo "Image '$enterprise_image_ref' does not exist locally; skipping" >&2 fi - - # Do substitutions to add extra details to every message. Without these - # substitutions, most messages won't have any information about which image - # the vulnerability was found in. - jq \ - ".runs[].tool.driver.name |= \"Trivy ${image_name}\"" \ - "$output" >"$output.tmp" - mv "$output.tmp" "$output" - jq \ - ".runs[].results[].locations[].physicalLocation.artifactLocation.uri |= \"${image_name}/\" + ." \ - "$output" >"$output.tmp" - mv "$output.tmp" "$output" - jq \ - ".runs[].results[].locations[].message.text |= \"${image_name}: \" + ." \ - "$output" >"$output.tmp" - mv "$output.tmp" "$output" done # Merge all SARIF files into one. From 339f3569876d1e2c347e61339713f0a780e7fc96 Mon Sep 17 00:00:00 2001 From: Hugo Dutka Date: Thu, 10 Jul 2025 18:11:39 +0200 Subject: [PATCH 2/3] revert to previous version --- scripts/scan_images.sh | 139 ++++++++++++++--------------------------- 1 file changed, 47 insertions(+), 92 deletions(-) diff --git a/scripts/scan_images.sh b/scripts/scan_images.sh index 33a83e9c..c9c74127 100755 --- a/scripts/scan_images.sh +++ b/scripts/scan_images.sh @@ -103,103 +103,58 @@ trivy_tmp_dir="$(mktemp -d -p "$PROJECT_ROOT")" trap 'rm -rf "$tmp_dir" "$trivy_tmp_dir"' EXIT -# Scan both example and enterprise images for image in "${IMAGES[@]}"; do - # Process example images (primary) - example_image_ref="codercom/example-${image}:${TAG}" - example_image_name="example-${image}-${TAG}" - example_output="${tmp_dir}/example-${image}-${TAG}.sarif" - - if docker image inspect "$example_image_ref" >/dev/null 2>&1; then - old_tmpdir="${TMPDIR:-}" - export TMPDIR="$trivy_tmp_dir" - - # The timeout is set to 15 minutes because in Java images it can take a while - # to scan JAR files for vulnerabilities. - run_trace $DRY_RUN trivy image \ - --severity CRITICAL,HIGH \ - --format sarif \ - --output "$example_output" \ - --timeout 15m0s \ - "$example_image_ref" 2>&1 | indent - - if [ "$old_tmpdir" = "" ]; then - unset TMPDIR - else - export TMPDIR="$old_tmpdir" - fi - - if [ $DRY_RUN = false ] && [ -f "$example_output" ]; then - # Do substitutions to add extra details to every message. Without these - # substitutions, most messages won't have any information about which image - # the vulnerability was found in. - jq \ - ".runs[].tool.driver.name |= \"Trivy ${example_image_name}\"" \ - "$example_output" >"$example_output.tmp" - mv "$example_output.tmp" "$example_output" - jq \ - ".runs[].results[].locations[].physicalLocation.artifactLocation.uri |= \"${example_image_name}/\" + ." \ - "$example_output" >"$example_output.tmp" - mv "$example_output.tmp" "$example_output" - jq \ - ".runs[].results[].locations[].message.text |= \"${example_image_name}: \" + ." \ - "$example_output" >"$example_output.tmp" - mv "$example_output.tmp" "$example_output" - elif [ $DRY_RUN = false ]; then - echo "No SARIF output found for image '$example_image_ref' at '$example_output'" >&2 - exit 1 - fi - else - echo "Image '$example_image_ref' does not exist locally; skipping" >&2 + image_ref="codercom/enterprise-${image}:${TAG}" + image_name="${image}-${TAG}" + output="${tmp_dir}/${image}-${TAG}.sarif" + + if ! docker image inspect "$image_ref" >/dev/null 2>&1; then + echo "Image '$image_ref' does not exist locally; skipping" >&2 + continue fi - # Process enterprise images (alias) - enterprise_image_ref="codercom/enterprise-${image}:${TAG}" - enterprise_image_name="enterprise-${image}-${TAG}" - enterprise_output="${tmp_dir}/enterprise-${image}-${TAG}.sarif" - - if docker image inspect "$enterprise_image_ref" >/dev/null 2>&1; then - old_tmpdir="${TMPDIR:-}" - export TMPDIR="$trivy_tmp_dir" - - # The timeout is set to 15 minutes because in Java images it can take a while - # to scan JAR files for vulnerabilities. - run_trace $DRY_RUN trivy image \ - --severity CRITICAL,HIGH \ - --format sarif \ - --output "$enterprise_output" \ - --timeout 15m0s \ - "$enterprise_image_ref" 2>&1 | indent - - if [ "$old_tmpdir" = "" ]; then - unset TMPDIR - else - export TMPDIR="$old_tmpdir" - fi - - if [ $DRY_RUN = false ] && [ -f "$enterprise_output" ]; then - # Do substitutions to add extra details to every message. Without these - # substitutions, most messages won't have any information about which image - # the vulnerability was found in. - jq \ - ".runs[].tool.driver.name |= \"Trivy ${enterprise_image_name}\"" \ - "$enterprise_output" >"$enterprise_output.tmp" - mv "$enterprise_output.tmp" "$enterprise_output" - jq \ - ".runs[].results[].locations[].physicalLocation.artifactLocation.uri |= \"${enterprise_image_name}/\" + ." \ - "$enterprise_output" >"$enterprise_output.tmp" - mv "$enterprise_output.tmp" "$enterprise_output" - jq \ - ".runs[].results[].locations[].message.text |= \"${enterprise_image_name}: \" + ." \ - "$enterprise_output" >"$enterprise_output.tmp" - mv "$enterprise_output.tmp" "$enterprise_output" - elif [ $DRY_RUN = false ]; then - echo "No SARIF output found for image '$enterprise_image_ref' at '$enterprise_output'" >&2 - exit 1 - fi + old_tmpdir="${TMPDIR:-}" + export TMPDIR="$trivy_tmp_dir" + + # The timeout is set to 15 minutes because in Java images it can take a while + # to scan JAR files for vulnerabilities. + run_trace $DRY_RUN trivy image \ + --severity CRITICAL,HIGH \ + --format sarif \ + --output "$output" \ + --timeout 15m0s \ + "$image_ref" 2>&1 | indent + + if [ "$old_tmpdir" = "" ]; then + unset TMPDIR else - echo "Image '$enterprise_image_ref' does not exist locally; skipping" >&2 + export TMPDIR="$old_tmpdir" fi + + if [ $DRY_RUN = true ]; then + continue + fi + + if [ ! -f "$output" ]; then + echo "No SARIF output found for image '$image_ref' at '$output'" >&2 + exit 1 + fi + + # Do substitutions to add extra details to every message. Without these + # substitutions, most messages won't have any information about which image + # the vulnerability was found in. + jq \ + ".runs[].tool.driver.name |= \"Trivy ${image_name}\"" \ + "$output" >"$output.tmp" + mv "$output.tmp" "$output" + jq \ + ".runs[].results[].locations[].physicalLocation.artifactLocation.uri |= \"${image_name}/\" + ." \ + "$output" >"$output.tmp" + mv "$output.tmp" "$output" + jq \ + ".runs[].results[].locations[].message.text |= \"${image_name}: \" + ." \ + "$output" >"$output.tmp" + mv "$output.tmp" "$output" done # Merge all SARIF files into one. From 326e893d3ef22b53e49b6203157dbaa830f37a81 Mon Sep 17 00:00:00 2001 From: Hugo Dutka Date: Thu, 10 Jul 2025 18:53:07 +0200 Subject: [PATCH 3/3] add inner loop for prefixes --- scripts/scan_images.sh | 106 +++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 51 deletions(-) diff --git a/scripts/scan_images.sh b/scripts/scan_images.sh index c9c74127..2b70629a 100755 --- a/scripts/scan_images.sh +++ b/scripts/scan_images.sh @@ -103,58 +103,62 @@ trivy_tmp_dir="$(mktemp -d -p "$PROJECT_ROOT")" trap 'rm -rf "$tmp_dir" "$trivy_tmp_dir"' EXIT +PREFIXES=("example" "enterprise") + for image in "${IMAGES[@]}"; do - image_ref="codercom/enterprise-${image}:${TAG}" - image_name="${image}-${TAG}" - output="${tmp_dir}/${image}-${TAG}.sarif" - - if ! docker image inspect "$image_ref" >/dev/null 2>&1; then - echo "Image '$image_ref' does not exist locally; skipping" >&2 - continue - fi - - old_tmpdir="${TMPDIR:-}" - export TMPDIR="$trivy_tmp_dir" - - # The timeout is set to 15 minutes because in Java images it can take a while - # to scan JAR files for vulnerabilities. - run_trace $DRY_RUN trivy image \ - --severity CRITICAL,HIGH \ - --format sarif \ - --output "$output" \ - --timeout 15m0s \ - "$image_ref" 2>&1 | indent - - if [ "$old_tmpdir" = "" ]; then - unset TMPDIR - else - export TMPDIR="$old_tmpdir" - fi - - if [ $DRY_RUN = true ]; then - continue - fi - - if [ ! -f "$output" ]; then - echo "No SARIF output found for image '$image_ref' at '$output'" >&2 - exit 1 - fi - - # Do substitutions to add extra details to every message. Without these - # substitutions, most messages won't have any information about which image - # the vulnerability was found in. - jq \ - ".runs[].tool.driver.name |= \"Trivy ${image_name}\"" \ - "$output" >"$output.tmp" - mv "$output.tmp" "$output" - jq \ - ".runs[].results[].locations[].physicalLocation.artifactLocation.uri |= \"${image_name}/\" + ." \ - "$output" >"$output.tmp" - mv "$output.tmp" "$output" - jq \ - ".runs[].results[].locations[].message.text |= \"${image_name}: \" + ." \ - "$output" >"$output.tmp" - mv "$output.tmp" "$output" + for prefix in "${PREFIXES[@]}"; do + image_ref="codercom/${prefix}-${image}:${TAG}" + image_name="${prefix}-${image}-${TAG}" + output="${tmp_dir}/${prefix}-${image}-${TAG}.sarif" + + if ! docker image inspect "$image_ref" >/dev/null 2>&1; then + echo "Image '$image_ref' does not exist locally; skipping" >&2 + continue + fi + + old_tmpdir="${TMPDIR:-}" + export TMPDIR="$trivy_tmp_dir" + + # The timeout is set to 15 minutes because in Java images it can take a while + # to scan JAR files for vulnerabilities. + run_trace $DRY_RUN trivy image \ + --severity CRITICAL,HIGH \ + --format sarif \ + --output "$output" \ + --timeout 15m0s \ + "$image_ref" 2>&1 | indent + + if [ "$old_tmpdir" = "" ]; then + unset TMPDIR + else + export TMPDIR="$old_tmpdir" + fi + + if [ $DRY_RUN = true ]; then + continue + fi + + if [ ! -f "$output" ]; then + echo "No SARIF output found for image '$image_ref' at '$output'" >&2 + exit 1 + fi + + # Do substitutions to add extra details to every message. Without these + # substitutions, most messages won't have any information about which image + # the vulnerability was found in. + jq \ + ".runs[].tool.driver.name |= \"Trivy ${image_name}\"" \ + "$output" >"$output.tmp" + mv "$output.tmp" "$output" + jq \ + ".runs[].results[].locations[].physicalLocation.artifactLocation.uri |= \"${image_name}/\" + ." \ + "$output" >"$output.tmp" + mv "$output.tmp" "$output" + jq \ + ".runs[].results[].locations[].message.text |= \"${image_name}: \" + ." \ + "$output" >"$output.tmp" + mv "$output.tmp" "$output" + done done # Merge all SARIF files into one.