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
7 changes: 4 additions & 3 deletions 10.0/aspnet/Dockerfile.rhel9
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ LABEL name="ubi9/dotnet-100-aspnet" \
aspnet_version="$ASPNET_VERSION"

USER 0
# Don't clutter the app user's HOME
ENV HOME=
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer this over letting root mess in the app user's HOME and then having to fix permissions for those files.
This way, we separate between the root and app user's HOME.


# Install packages:
# - aspnetcore-runtime-*: provides the ASP.NET Core shared framework.
Expand All @@ -36,8 +38,7 @@ RUN [ "$IS_CI" == "true" ] || ( \
dotnet --list-runtimes | grep "Microsoft.NETCore.App ${DOTNET_VERSION} " && \
dotnet --list-runtimes | grep "Microsoft.AspNetCore.App ${ASPNET_VERSION} " )

# Ensure we didn't add anything to HOME that is owned by root.
RUN chown -R $APP_UID:0 /opt/app-root && fix-permissions /opt/app-root

# Run container rootless.
USER $APP_UID
# Set HOME for the random uid that runs the s2i app on OpenShift
ENV HOME=/opt/app-root
55 changes: 34 additions & 21 deletions 10.0/build/Dockerfile.rhel9
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,24 @@ ARG DOTNET_SDK_VERSION=10.0
ARG IS_CI
ARG DOTNET_TARBALL

ENV PATH=/opt/app-root/src/.local/bin:/opt/app-root/src/bin:/opt/app-root/.dotnet/tools:${PATH} \
# Expose the port in case the SDK image is used as a base image through s2i.
EXPOSE 8080

ENV \
# Add s2i bin dirs and .NET tools dir to PATH
PATH=/opt/app-root/.dotnet/tools:/opt/app-root/src/.local/bin:/opt/app-root/src/bin:/opt/app-root/bin:${PATH} \
# S2I
STI_SCRIPTS_PATH=/usr/libexec/s2i \
DOTNET_APP_PATH=/opt/app-root/app \
DOTNET_DEFAULT_CMD=default-cmd.sh \
# Don't generate a developer certificate
DOTNET_GENERATE_ASPNET_CERTIFICATE=false \
# Don't download/extract docs for nuget packages
NUGET_XMLDOC_MODE=skip \
# This skips the first time running text
DOTNET_NOLOGO=true \
# Needed for the `dotnet watch` to detect changes in a container
DOTNET_USE_POLLING_FILE_WATCHER=true \
# Like Microsoft images, provide the SDK version
DOTNET_SDK_VERSION=$DOTNET_SDK_VERSION

Expand All @@ -31,26 +44,28 @@ LABEL name="ubi9/dotnet-100" \

# Switch to root for package installs
USER 0
# Don't let root clutter the app user's HOME
ENV HOME=

# Each language image can have 'contrib' a directory with extra files needed to
# run and build the applications.
COPY ./contrib/ /opt/app-root
# Helper scripts the user can call
COPY ./root/usr/bin /usr/bin

# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH.
COPY ./s2i/bin/ /usr/libexec/s2i

# Install packages:
# - dotnet-sdk--*: provides the .NET SDK.
# - procps-ng: provides 'pidof' which is needed by the 'odo' Devfile to find the running 'dotnet' process.
# - findutils: provides 'find' which is used by the 'fix-permissions' script.
RUN [ -n "${DOTNET_TARBALL}" ] || ( \
INSTALL_PKGS="dotnet-sdk-10.0 procps-ng" && \
INSTALL_PKGS="dotnet-sdk-10.0 procps-ng findutils" && \
microdnf install -y --setopt=tsflags=nodocs --setopt=install_weak_deps=0 $INSTALL_PKGS && \
microdnf clean all -y && \
# yum cache files may still exist (and quite large in size)
rm -rf /var/cache/yum/* )
# Tarball install (in the runtime base image)
RUN [ -z "${DOTNET_TARBALL}" ] || ( \
INSTALL_PKGS="procps-ng" && \
INSTALL_PKGS="procps-ng findutils" && \
microdnf install -y --setopt=tsflags=nodocs --setopt=install_weak_deps=0 $INSTALL_PKGS && \
microdnf clean all -y && \
# yum cache files may still exist (and quite large in size)
Expand All @@ -64,24 +79,22 @@ RUN [ "$IS_CI" == "true" ] || ( \
printf "Checking SDK version ${DOTNET_SDK_VERSION} against:\n$(dotnet --list-sdks)" && \
dotnet --list-sdks | grep "^${DOTNET_SDK_VERSION} " )

# Directory with the sources is set as the working directory.
RUN mkdir /opt/app-root/src
WORKDIR /opt/app-root/src

# Build the container tool.
RUN /usr/libexec/s2i/container-tool build-tool

# Since $HOME is set to /opt/app-root, the yum install may have created config
# directories (such as ~/.pki/nssdb) there. These will be owned by root and can
# cause actions that work on all of /opt/app-root to fail. So we need to fix
# the permissions on those too.
RUN chown -R $APP_UID:0 /opt/app-root && fix-permissions /opt/app-root
# Run as the s2i assemble user
USER $APP_UID
# Set HOME for the random uid that runs the s2i app on OpenShift
ENV HOME=/opt/app-root

# Needed for the `dotnet watch` to detect changes in a container
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
# Create s2i directories used for sources and published app
RUN mkdir -p /opt/app-root/src ${DOTNET_APP_PATH}

# Run container rootless.
USER $APP_UID
# Trigger first run to create .NET SDK dirs and config files under $HOME.
RUN dotnet help

# Fix permissions on HOME for the random uid that runs the s2i app on OpenShift
RUN fix-permissions /opt/app-root

# Set the default CMD to start a shell.
CMD /bin/bash
# Use the s2i dir for sources as the working dir
WORKDIR /opt/app-root/src
6 changes: 6 additions & 0 deletions 10.0/build/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,9 @@ an `.s2i/environment` file inside your source code repository.
* **DOTNET_SDK_VERSION**

This variable contains the version of the SDK.

* **DOTNET_APP_PATH,DOTNET_DEFAULT_CMD**

These variables are used by source-to-image. `DOTNET_APP_PATH` is the directory that gets published to by the s2i `assemble` script.
The s2i `run` script makes it the working directory and then starts the script named `$DOTNET_DEFAULT_CMD` (`default-cmd.sh`) in that directory.
That script is responsible for starting the .NET application.
5 changes: 0 additions & 5 deletions 10.0/build/contrib/etc/trust_ssl_dirs

This file was deleted.

3 changes: 0 additions & 3 deletions 10.0/build/s2i/bin/assemble
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,6 @@ fi
if [ "$BUILD_TYPE" == "source" ]; then
echo "Using SDK: $(dotnet --version)"

# Print DOTNET_SSL_DIRS unsupported.
source /opt/app-root/etc/trust_ssl_dirs

# dotnet tools
if [ -n "${DOTNET_TOOLS}" ]; then
# Build nuget sources list for when doing the restore
Expand Down
3 changes: 0 additions & 3 deletions 10.0/build/s2i/bin/run
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#!/bin/bash
set -e

# Print DOTNET_SSL_DIRS unsupported.
source /opt/app-root/etc/trust_ssl_dirs

if [ -n "${DOTNET_INFO}" ]; then
/usr/libexec/s2i/container-tool info
fi
Expand Down
75 changes: 13 additions & 62 deletions 10.0/build/test/run
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@
# short image name such as 'foobar', or it may be a fully qualified name in the
# form of example.com/project/repository/image@sha256:hashinhex
#
# ASPNET_IMAGE_NAME specifies the name of the runtime image used for split
# builds. If blank or unset, it is computed automatically as the base image
# used to build IMAGE_NAME.
#
# OPENSHIFT_ONLY environment variable, if 'true', only tests features used by
# OpenShift's try-it feature.
#
Expand All @@ -37,14 +33,6 @@ IMAGE_OS=${IMAGE_OS:-RHEL8}

IMAGE_NAME=${IMAGE_NAME:-localhost/ubi9/dotnet-100}
# Infer runtime image from SDK image when it is not explicitly set
if [[ ${ASPNET_IMAGE_NAME:-} == "" ]]; then
if [[ $(podman images -n --filter reference="${IMAGE_NAME}") == "" ]]; then
podman pull "${IMAGE_NAME}"
fi
base_image=$(podman image history --format json "${IMAGE_NAME}" | jq -r '[.[].comment | select (. != null )][0]' | cut -d' ' -f2)
echo "${base_image}"
ASPNET_IMAGE_NAME="${base_image}"
fi
OPENSHIFT_ONLY=${OPENSHIFT_ONLY:-false}

test_dir="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")"
Expand Down Expand Up @@ -128,6 +116,11 @@ test_image() {
# This is to ensure it is provided as environment variables.
assert_contains $(docker_get_env $IMAGE_NAME DOTNET_SDK_VERSION) "$dotnet_version_series"

# DOTNET_DEFAULT_CMD
assert_equal $(docker_get_env $IMAGE_NAME DOTNET_DEFAULT_CMD) "default-cmd.sh"
# DOTNET_APP_PATH
assert_equal $(docker_get_env $IMAGE_NAME DOTNET_APP_PATH) "/opt/app-root/app"

# Verify $HOME != $CWD. See https://github.com/redhat-developer/s2i-dotnetcore/issues/28
local working_dir=$(docker_run ${IMAGE_NAME} pwd)
assert_equal "${working_dir}" "/opt/app-root/src"
Expand All @@ -149,6 +142,13 @@ test_image() {
assert_contains "${certificate_stores}" "No such file or directory"
}

test_port() {
test_start

# Port 8080 is exposed (for s2i based apps)
assert_equal $(docker_get_exposedports $IMAGE_NAME) '{"8080/tcp":{}}'
}

test_consoleapp() {
test_start

Expand Down Expand Up @@ -410,54 +410,6 @@ test_config() {
test_config_3
}

test_split_build() {
test_start

# test openshift chained build
# see 'chaining builds' in the openshift docs

# this app has DOTNET_PACK=true
local app=asp-net-hello-world-envvar

local build_dir="${test_dir}/split_build"
rm -rf "$build_dir"
mkdir "$build_dir"
pushd "$build_dir" > /dev/null

# extract app.tar.gz from build
local image=$(s2i_build ${app})
local container=$(docker create ${image})
docker cp ${container}:/opt/app-root/app.tar.gz app.tar.gz
# cleanup
docker_rm ${container}
docker_rmi ${image}

# create image based on app.tar.gz
# we don't need to provide a CMD statement
# app.tar.gz has a default-cmd.sh which matches with the runtime CMD.
cat >Dockerfile <<EOF
FROM ${ASPNET_IMAGE_NAME}
ADD app.tar.gz .
EOF
image=$(docker_build .)

# user to run the app (31002) is different than user that built the app (1001).
local run_user=31002
# start container
local container=$(docker_run_as_d ${image} ${run_user})
local url=$(container_url ${container})
# request
local response=$(curl_retry ${url}/)
# cleanup
docker_rm ${container}
docker_rmi ${image}

# app works
assert_equal "${response}" "Hello world"

popd > /dev/null
}

test_imagestream_sample() {
test_start

Expand Down Expand Up @@ -606,10 +558,10 @@ test_msbuild_exec_task() {
}

info "Testing ${IMAGE_NAME}"
info "Using runtime image ${ASPNET_IMAGE_NAME}"

if [ ${OPENSHIFT_ONLY} != true ]; then
test_image
test_port
test_config
test_usage
test_default_cmd
Expand All @@ -621,7 +573,6 @@ if [ ${OPENSHIFT_ONLY} != true ]; then
test_vb
test_published_files
test_aspnetapp
test_split_build
test_templates
test_user
test_binary
Expand Down
36 changes: 8 additions & 28 deletions 10.0/runtime/Dockerfile.rhel9
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,9 @@ ARG DOTNET_VERSION=10.0
ARG IS_CI
ARG DOTNET_TARBALL

# This image provides a .NET 10.0 environment you can use to run your .NET
# applications.
EXPOSE 8080

ENV HOME=/opt/app-root \
PATH=/opt/app-root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
DOTNET_APP_PATH=/opt/app-root/app \
DOTNET_DATA_PATH=/opt/app-root/data \
DOTNET_DEFAULT_CMD=default-cmd.sh \
ENV \
# Microsoft's images set this to enable detecting when an app is running in a container.
DOTNET_RUNNING_IN_CONTAINER=true \
# Don't download/extract docs for nuget packages
NUGET_XMLDOC_MODE=skip \
# Configure ASP.NET Core to use the exposed port
ASPNETCORE_URLS=http://*:8080 \
# Like Microsoft images, set APP_UID to the UID of the non-root user.
Expand All @@ -39,13 +29,11 @@ LABEL name="ubi9/dotnet-100-runtime" \
dotnet_version_major_minor="10.0" \
dotnet_version="$DOTNET_VERSION"

COPY ./root/usr/bin /usr/bin

# Install packages:
# - dotnet-runtime-*: provides the .NET shared framework.
# - findutils: provides 'find' which is used by the 'fix-permissions' script.
# - tar, gzip: enable installing vsdbg into the image for debugging.
RUN [ -n "${DOTNET_TARBALL}" ] || ( \
INSTALL_PKGS="dotnet-runtime-10.0 findutils shadow-utils tar gzip" && \
INSTALL_PKGS="dotnet-runtime-10.0 tar gzip" && \
microdnf install -y --setopt=tsflags=nodocs --setopt=install_weak_deps=0 $INSTALL_PKGS && \
# ubi-minimal doesn't include timezones, restore them.
( microdnf reinstall tzdata -y || microdnf update tzdata -y ) && \
Expand All @@ -54,7 +42,7 @@ RUN [ -n "${DOTNET_TARBALL}" ] || ( \
rm -rf /var/cache/yum/* )
# Add .NET from a tarball for CI/development.
RUN [ -z "${DOTNET_TARBALL}" ] || ( \
microdnf install -y tar gzip unzip shadow-utils libicu && \
microdnf install -y tar gzip unzip libicu && \
( microdnf reinstall tzdata -y || microdnf update tzdata -y ) && \
curl "${DOTNET_TARBALL}" -o /tmp/dotnet.tar.gz && \
mkdir /opt/dotnet && \
Expand All @@ -69,18 +57,10 @@ RUN [ "$IS_CI" == "true" ] || ( \
dotnet --list-runtimes | grep "Microsoft.NETCore.App ${DOTNET_VERSION} " )

# Add default user
RUN mkdir -p ${DOTNET_APP_PATH} ${DOTNET_DATA_PATH} && \
useradd -u $APP_UID -r -g 0 -d ${HOME} -s /sbin/nologin \
-c "Default Application User" default

WORKDIR ${DOTNET_APP_PATH}
COPY default-cmd.sh ${DOTNET_DEFAULT_CMD}
CMD "./${DOTNET_DEFAULT_CMD}"

# In order to drop the root user, we have to make some directories world
# writable as OpenShift default security model is to run the container under
# random UID.
RUN chown -R $APP_UID:0 /opt/app-root && fix-permissions /opt/app-root
RUN useradd -u $APP_UID -r -g 0 -d /opt/app-root -s /sbin/nologin -c "Default Application User" default && \
install -d -m 0775 -o $APP_UID -g 0 /opt/app-root

# Run container rootless.
USER $APP_UID
# Set HOME for the random uid that runs the s2i app on OpenShift
ENV HOME=/opt/app-root
5 changes: 0 additions & 5 deletions 10.0/runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ They must not to be overridden.
This variable is set to `http://*:8080` to configure ASP.NET Core to use the
port exposed by the image.

* **DOTNET_APP_PATH,DOTNET_DEFAULT_CMD,DOTNET_DATA_PATH**

These variables contain the working directory (`/opt/app-root/app`), the default CMD of the runtime image (`default-cmd.sh`)
and an empty folder you can use to store your application data (`/opt/app-root/data`) and make persistent with a volume mount.

* **SSL_CERT_DIR**

Used to specify a list of colon (`:`) separated directories with certificates to trust.
Expand Down
Loading