- Introduction
- Getting-Started
- Install & Execute .NET application
- Explore-GitHub
- Explore-Quay.io
- Explore-Podman
- Deploy-Message-App-Manually
- Deploy-Message-App-with-S2I
- Deploy-Website-with-ASP.Net-Core-&-Blazor
- Deploy-the-.NET-game-using-Shift-tool
- Deploy-.NET-game-with-build-image
- Optional-Unguided-Exercises
- Summary-and-Next-Steps
1 Introduction
Welcome to the .NET on IBM Power hands-on lab guide. This workshop demonstrates development, deployment, and migration paths for .NET applications on IBM Power systems, covering both Red Hat Enterprise Linux (RHEL) and Red Hat OpenShift Container Platform (OCP) environments.
Lab Environments
RHEL Bastion Server
You’ll work with a RHEL-based Bastion server where you’ll:
– Install and configure .NET SDK 7.0
– Create and run basic .NET applications directly on Linux
– Test applications in a traditional server environment
– Build container images using Podman
– Perform version upgrades and migrations
OpenShift Container Platform
You’ll explore OpenShift capabilities including:
– Container-based deployments of .NET applications
– Source-to-Image (S2I) builds
– Automated deployment workflows
– Container orchestration and scaling
– Web-based application access through OpenShift routes
What You’ll Learn
Throughout this lab, you’ll gain hands-on experience with:
– Setting up development environments for .NET on IBM Power
– Creating and testing basic .NET applications
– Working with source code using Git and GitHub
– Building and deploying applications using various methods:
– Direct execution on RHEL
– Manual containerization with Podman
– OpenShift S2I deployment
– Deployment using specialized tools (dotnet-shift and build-image)
– Migrating applications through .NET versions:
– Understanding the migration path from .NET 7.0 to 8.0 and 9.0
– Handling breaking changes and compatibility issues
– Testing and validating migrations
– Updating container images and deployments
Prerequisites
Before starting the lab, ensure you have access to:
– A RHEL-based Bastion LPAR (Logical Partition)
– An OpenShift Container Platform (OCP) environment running on IBM Power
– OpenShift user credentials (default username: cecuser)
– Basic familiarity with Linux commands and container concepts
Lab Structure
The lab progresses through several sections:
1. Getting Started: Environment setup and configuration
2. Basic .NET Application Development on RHEL
3. Source Code Management with GitHub
4. Container Registry Exploration with Quay.io
5. OpenShift Deployment Methods
6. Advanced Deployment Tools and Techniques
7. Version Migration Procedures:
– Assessing application readiness for migration
– Updating code and dependencies
– Testing on new .NET versions
– Deploying upgraded applications
8. Optional Extended Exercises
Each section provides detailed instructions with expected outputs to help you verify your progress. The migration section will be particularly valuable for organizations planning their .NET upgrade strategy on IBM Power systems.
The lab concludes with optional unguided exercises for further exploration of .NET development, deployment, and migration scenarios on IBM Power systems.
Let’s begin by setting up your environments and getting familiar with the tools you’ll be using throughout this lab.
2 Getting Started
Please Note:
Commands that you should execute are displayed in bold blue txt. Left click within this area to copy the command to you clipboard.
Example output from commands that have been executed are displayed with white txt with black background.
- Bullet items are required actions
Standard paragraphs are for informational purposes.
2.1 Assumptions
- You have access to an OpenShift Container Platform (OCP) environment running on IBM Power10
- Make a note of the OCP Console URL
- You have access to a RHEL based Bastion LPAR
- Make a note of the Bastion IP address
- The OCP user that you use is “cecuser”, if not, then just substitute “cecuser” for your own OCP user name
- Make a note the OCP user name, if not using “cecuser”
- Make a note of the “cecuser” password
2.2 Connect to the Bastion CLI
Now we will go over the steps to connect to the CLI for the environment.
I typically use the Putty application, but you are free to use your favourite terminal.
Putty is available for download HERE
- Install Putty from the above link if desired.
- Open the Putty application.

- Fill the hostname with the IP address of your Bastion. This may be found in your assigned Project Kit if using IBM TechZone resources.

- Press Open

- Click Accept

- You will see a “login as:” prompt, type cecuser and press enter:

- Enter the password for the “cecuser” user. This will be the same for both the CLI and for the GUI.
2.3 Login to OpenShift
You can watch a silent recording of this exercise
To login to the OpenShift environment from the command line, find the oc login command from your OpenShift GUI.
- Point your browser to your OpenShift web console
- Accept the certificate warning if certificates have not been configured correctly on demo equipment.

- Click on the htpasswd option:

- Add your user and password contained on the step 1 and Click login.

- Familiarize yourself with the navigation for approximately 10 minutes if it’s your first time. You can easily switch between Developer and Administrator views using the menu option located at the top left corner.

2.4 Copy login command for CLI use
You may watch a silent recording of this exercise
If you need to login again to the CLI, for any reason, you can find the login command on main OpenShift web console page.
- On the top right side, you will see the cecuser drop down click on it and then on “Copy login command”

- Once again click on the htpasswd option:

- Add your user and password contained on the step 1 and Click login.

- Click on Display Token on the top left

- You can use the oc login command whenever your Authorization is expired. You may need to use the API token for login in into the registry.

- As cecuser, copy and paste the oc login command from the web page into your Putty Session.
oc login --token=[Add your own token] server=[Add you own server]
For example:
oc login --token=sha256~8HzJyuecqujfeCXsaDnAeUUJ9VMsLafr-cJk5yn8tGk --server=https://api.p1289.cecc.ihost.com:6443
Logged into "https://api.p1289.cecc.ihost.com:6443" as "cecuser" using the token provided.You have access to 71 projects, the list has been suppressed. You can list all projects with 'oc projects'Using project "default".
3 Install & Execute .NET application
You can watch a recording of this lab
- Use the dnf command to install .NET as the root user. You can copy and paste the commands in bold below. Enter Y to continue with installation when asked.
sudo dnf install dotnet-sdk-7.0
Updating Subscription Management repositories.
Red Hat Enterprise Linux 8 for Power, little en 96 kB/s | 3.8 kB 00:00
Red Hat Enterprise Linux 8 for Power, little en 72 kB/s | 2.9 kB 00:00
Red Hat Enterprise Linux 8 for Power, little en 90 kB/s | 4.1 kB 00:00
Dependencies resolved.
================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
dotnet ppc64le 7.0.105-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 18 k
Installing dependencies:
aspnetcore-runtime-7.0
ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 2.8 M
aspnetcore-targeting-pack-7.0
ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 1.6 M
dotnet-apphost-pack-7.0
ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 100 k
dotnet-host ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 199 k
dotnet-hostfxr-7.0
ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 174 k
dotnet-runtime-7.0
ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 7.8 M
dotnet-sdk-7.0 ppc64le 7.0.105-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 52 M
dotnet-targeting-pack-7.0
ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 2.9 M
dotnet-templates-7.0
ppc64le 7.0.105-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 3.9 M
netstandard-targeting-pack-2.1
ppc64le 7.0.105-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 1.5 M
Transaction Summary
================================================================================
Install 11 Packages
Total download size: 73 M
Installed size: 308 M
Is this ok [y/N]: y
Downloading Packages:
(1/11): dotnet-7.0.105-2.el8_8.ppc64le.rpm 203 kB/s | 18 kB 00:00
(2/11): dotnet-apphost-pack-7.0-7.0.5-2.el8_8.ppc64le.rpm 1.8 MB/s | 100 kB 00:00
(3/11): aspnetcore-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le.rpm 10 MB/s | 1.6 MB 00:00
(4/11): aspnetcore-runtime-7.0-7.0.5-2.el8_8.ppc64le.rpm 14 MB/s | 2.8 MB 00:00
(5/11): dotnet-host-7.0.5-2.el8_8.ppc64le.rpm 3.4 MB/s | 199 kB 00:00
(6/11): dotnet-hostfxr-7.0-7.0.5-2.el8_8.ppc64le.rpm 2.8 MB/s | 174 kB 00:00
(7/11): dotnet-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le.rpm 16 MB/s | 2.9 MB 00:00
(8/11): dotnet-runtime-7.0-7.0.5-2.el8_8.ppc64le.rpm 22 MB/s | 7.8 MB 00:00
(9/11): dotnet-templates-7.0-7.0.105-2.el8_8.ppc64le.rpm 18 MB/s | 3.9 MB 00:00
(10/11): netstandard-targeting-pack-2.1-7.0.105-2.el8_8.ppc64le.rpm 14 MB/s | 1.5 MB 00:00
(11/11): dotnet-sdk-7.0-7.0.105-2.el8_8.ppc64le.rpm 48 MB/s | 52 MB 00:01
----------------------------------------------------------------------------------------------------------------------
Total 56 MB/s | 73 MB 00:01
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : dotnet-host-7.0.5-2.el8_8.ppc64le 1/11
Installing : aspnetcore-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le 2/11
Installing : dotnet-apphost-pack-7.0-7.0.5-2.el8_8.ppc64le 3/11
Installing : dotnet-hostfxr-7.0-7.0.5-2.el8_8.ppc64le 4/11
IBM TechXchange 2024 / © 2024 IBM Corporation
11
Installing : dotnet-runtime-7.0-7.0.5-2.el8_8.ppc64le 5/11
Installing : aspnetcore-runtime-7.0-7.0.5-2.el8_8.ppc64le 6/11
Installing : dotnet-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le 7/11
Installing : dotnet-templates-7.0-7.0.105-2.el8_8.ppc64le 8/11
Installing : netstandard-targeting-pack-2.1-7.0.105-2.el8_8.ppc64le 9/11
Installing : dotnet-sdk-7.0-7.0.105-2.el8_8.ppc64le 10/11
Installing : dotnet-7.0.105-2.el8_8.ppc64le 11/11
Running scriptlet: dotnet-7.0.105-2.el8_8.ppc64le 11/11
Verifying : aspnetcore-runtime-7.0-7.0.5-2.el8_8.ppc64le 1/11
Verifying : aspnetcore-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le 2/11
Verifying : dotnet-7.0.105-2.el8_8.ppc64le 3/11
Verifying : dotnet-apphost-pack-7.0-7.0.5-2.el8_8.ppc64le 4/11
Verifying : dotnet-host-7.0.5-2.el8_8.ppc64le 5/11
Verifying : dotnet-hostfxr-7.0-7.0.5-2.el8_8.ppc64le 6/11
Verifying : dotnet-runtime-7.0-7.0.5-2.el8_8.ppc64le 7/11
Verifying : dotnet-sdk-7.0-7.0.105-2.el8_8.ppc64le 8/11
Verifying : dotnet-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le 9/11
Verifying : dotnet-templates-7.0-7.0.105-2.el8_8.ppc64le 10/11
Verifying : netstandard-targeting-pack-2.1-7.0.105-2.el8_8.ppc64le 11/11
Installed products updated.
Installed:
aspnetcore-runtime-7.0-7.0.5-2.el8_8.ppc64le aspnetcore-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le
dotnet-7.0.105-2.el8_8.ppc64le dotnet-apphost-pack-7.0-7.0.5-2.el8_8.ppc64le
dotnet-host-7.0.5-2.el8_8.ppc64le dotnet-hostfxr-7.0-7.0.5-2.el8_8.ppc64le
dotnet-runtime-7.0-7.0.5-2.el8_8.ppc64le dotnet-sdk-7.0-7.0.105-2.el8_8.ppc64le
dotnet-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le dotnet-templates-7.0-7.0.105-2.el8_8.ppc64le
netstandard-targeting-pack-2.1-7.0.105-2.el8_8.ppc64le
Complete!
- Check the version of .NET installed. .NET was made available from Red Hat at version 7 in Nov ’22. Version 8 is currently target GA Nov ’23. Both .NET 8.0 and 9.0 have been released since the creation of this lab.
dotnet --version
7.0.105
Create basic .NET application
In this section we will create a “Hello World” project.
- Create a new project called “hello” to host a “hello world” simple application. We can use new console to do that.
dotnet new console -o MyApp -f net7.0
The template "Console App" was created successfully.
Processing post-creation actions...
Restoring /home/cecuser/MyApp/MyApp.csproj:
Determining projects to restore...
Restored /home/cecuser/MyApp/MyApp.csproj (in 240 ms).
Restore succeeded.
- Change into the project directory
cd MyApp
- The main file in the MyApp folder is called Program.cs. By default, it already contains the necessary code to write Hello, World! to the console. Take a look at the Hello World code
cat Program.cs
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
- Now let’s run the app and make a note of the runtime.
time dotnet run
Hello, World!
real 0m4.547s
user 0m4.717s
sys 0m0.121s
- Open the Program.cs file in any text or code editor, (I use vi). The Program.cs file is located on the newly created MyApp directory. Then, add the additional line to print the current time.
vi Program.cs
Console.WriteLine("The current time is " + DateTime.Now);
cat Program.cs
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
Console.WriteLine("The current time is " + DateTime.Now);
- Now let’s run the app again and note the change.
time dotnet run
Hello, World!
The current time is 6/6/2023 2:46:52 PM
real 0m8.838s
user 0m4.926s
sys 0m0.130s
- Now let’s publish the application. dotnet publish compiles the application, reads through its dependencies specified in the project file (*.csproj), and publishes the resulting set of files to a directory. The dotnet publish command’s output is ready for deployment to a hosting system.
dotnet publish
MSBuild version 17.4.3+7e646be43 for .NET
Determining projects to restore...
All projects are up-to-date for restore.
MyApp -> /home/cecuser/MyApp/bin/Debug/net7.0/MyApp.dll
MyApp -> /home/cecuser/MyApp/bin/Debug/net7.0/publish/
- Now let’s run the compiled version and compare the run time from before. Note how much faster that was than before the publish!
time dotnet ./bin/Debug/net7.0/MyApp.dll
Hello, World!
The current time is 6/6/2023 3:06:47 PM
real 0m0.256s
user 0m0.246s
sys 0m0.011s
4. Explore GitHub
You can watch a recording of this exercise
Install git on Power with RHEL 8
- Use the dnf command to install git as the root user. Enter Y, to continue with installation.
sudo dnf install git
Updating Subscription Management repositories.
Red Hat Enterprise Linux 8 for Power, little endian - Supplementary (RPMs) 80 kB/s | 3.8 kB 00:00
Red Hat Enterprise Linux 8 for Power, little endian - AppStream (RPMs) 77 kB/s | 2.9 kB 00:00
Red Hat Enterprise Linux 8 for Power, little endian - BaseOS (RPMs) 103 kB/s | 4.1 kB 00:00
Dependencies resolved.
======================================================================================================================
Package Architecture Version Repository Size
======================================================================================================================
Installing:
git ppc64le 2.39.3-1.el8_8 rhel-8-for-ppc64le-appstream-rpms 104 k
Installing dependencies:
git-core ppc64le 2.39.3-1.el8_8 rhel-8-for-ppc64le-appstream-rpms 12 M
git-core-doc noarch 2.39.3-1.el8_8 rhel-8-for-ppc64le-appstream-rpms 3.0 M
perl-Error noarch 1:0.17025-2.el8 rhel-8-for-ppc64le-appstream-rpms 46 k
perl-Git noarch 2.39.3-1.el8_8 rhel-8-for-ppc64le-appstream-rpms 79 k
perl-TermReadKey ppc64le 2.37-7.el8 rhel-8-for-ppc64le-appstream-rpms 42 k
Transaction Summary
======================================================================================================================
Install 6 Packages
Total download size: 15 M
Installed size: 53 M
Is this ok [y/N]: y
Downloading Packages:
(1/6): git-2.39.3-1.el8_8.ppc64le.rpm 2.1 MB/s | 104 kB 00:00
(2/6): perl-Error-0.17025-2.el8.noarch.rpm 1.7 MB/s | 46 kB 00:00
(3/6): perl-Git-2.39.3-1.el8_8.noarch.rpm 2.3 MB/s | 79 kB 00:00
(4/6): git-core-doc-2.39.3-1.el8_8.noarch.rpm 20 MB/s | 3.0 MB 00:00
(5/6): perl-TermReadKey-2.37-7.el8.ppc64le.rpm 1.0 MB/s | 42 kB 00:00
(6/6): git-core-2.39.3-1.el8_8.ppc64le.rpm 41 MB/s | 12 MB 00:00
----------------------------------------------------------------------------------------------------------------------
Total 51 MB/s | 15 MB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : git-core-2.39.3-1.el8_8.ppc64le 1/6
Installing : git-core-doc-2.39.3-1.el8_8.noarch 2/6
Installing : perl-TermReadKey-2.37-7.el8.ppc64le 3/6
Installing : perl-Error-1:0.17025-2.el8.noarch 4/6
Installing : perl-Git-2.39.3-1.el8_8.noarch 5/6
Installing : git-2.39.3-1.el8_8.ppc64le 6/6
Running scriptlet: git-2.39.3-1.el8_8.ppc64le 6/6
Verifying : git-2.39.3-1.el8_8.ppc64le 1/6
Verifying : git-core-2.39.3-1.el8_8.ppc64le 2/6
Verifying : git-core-doc-2.39.3-1.el8_8.noarch 3/6
Verifying : perl-Error-1:0.17025-2.el8.noarch 4/6
Verifying : perl-Git-2.39.3-1.el8_8.noarch 5/6
Verifying : perl-TermReadKey-2.37-7.el8.ppc64le 6/6
Installed products updated.
IBM TechXchange 2024 / © 2024 IBM Corporation
15
Installed:
git-2.39.3-1.el8_8.ppc64le git-core-2.39.3-1.el8_8.ppc64le git-core-doc-2.39.3-1.el8_8.noarch
perl-Error-1:0.17025-2.el8.noarch perl-Git-2.39.3-1.el8_8.noarch perl-TermReadKey-2.37-7.el8.ppc64le
Complete!
- Check the level version of git installed
git --version
git version 2.39.3
Explore GitHub repositories containing .NET source
In this section we will four GitHub repositories containing .NET application source.
- Explore Paul Chapman’s overview page on GitHub.
https://github.com/paulchapmanibm

- Explore Paul’s Repositories page on GitHub
https://github.com/paulchapmanibm?tab=repositories

- Explore Paul’s SignalRChat repository
https://github.com/paulchapmanibm/SignalRChat

- Explore Paul’s stayingalive repository
https://github.com/paulchapmanibm/stayingalive

- Explore Paul’s Blazor1App1 repository
https://github.com/paulchapmanibm/BlazorApp1

- Explore Paul’s Blazor1App1 repository
https://github.com/paulchapmanibm/myMLApp

Clone SignalRchat source
In this section we will clone .NET application using SignalR library.
ASP.NET Core SignalR is an open-source library that simplifies adding real-time web functionality to apps. Realtime web functionality enables server-side code to push content to clients instantly. Good candidates for SignalR: Apps that require high frequency updates from the server.
- Change to cecuser home directory.
cd
- Create a build directory
mkdir build
- Change to the new build directory
cd build
- Now let’s clone the SignalRchat source code from GitHub to our Power server
git clone https://github.com/paulchapmanibm/SignalRChat.git
Cloning into 'SignalRChat'...
remote: Enumerating objects: 158, done.
remote: Counting objects: 100% (158/158), done.
remote: Compressing objects: 100% (104/104), done.
remote: Total 158 (delta 60), reused 139 (delta 46), pack-reused 0
Receiving objects: 100% (158/158), 906.94 KiB | 9.45 MiB/s, done.
Resolving deltas: 100% (60/60), done.
- Next, clone the stayingalive repository
git clone https://github.com/paulchapmanibm/stayingalive.git
Cloning into 'stayingalive'...
remote: Enumerating objects: 136, done.
remote: Counting objects: 100% (136/136), done.
remote: Compressing objects: 100% (88/88), done.
remote: Total 136 (delta 54), reused 114 (delta 42), pack-reused 0
Receiving objects: 100% (136/136), 865.36 KiB | 14.42 MiB/s, done.
Resolving deltas: 100% (54/54), done.
- Next, clone the BlazorApp1 repository
git clone https://github.com/paulchapmanibm/BlazorApp1
- Finally, clone the myMLApp repository
git clone https://github.com/paulchapmanibm/myMLApp.git
Cloning into 'myMLApp'...
remote: Enumerating objects: 39, done.
remote: Counting objects: 100% (39/39), done.
remote: Compressing objects: 100% (26/26), done.
remote: Total 39 (delta 10), reused 26 (delta 7), pack-reused 0
Receiving objects: 100% (39/39), 238.10 KiB | 8.21 MiB/s, done.
Resolving deltas: 100% (10/10), done.
- Now, take some time to review the directory structure of the cloned repositories
ls -lR SignalRChat
SignalRChat:
total 20
-rw-rw-r--. 1 cecuser cecuser 1243 Jun 6 16:44 Dockerfile
-rw-rw-r--. 1 cecuser cecuser 1243 Jun 6 16:44 Dockerfile.ppc64le
-rw-rw-r--. 1 cecuser cecuser 705 Jun 6 16:44 Dockerfile.x86
-rw-rw-r--. 1 cecuser cecuser 2032 Jun 6 16:44 README.md
drwxrwxr-x. 6 cecuser cecuser 251 Jun 6 16:44 SignalRChat
-rw-rw-r--. 1 cecuser cecuser 1114 Jun 6 16:44 SignalRChat.sln
SignalRChat/SignalRChat:
total 28
-rw-rw-r--. 1 cecuser cecuser 145 Jun 6 16:44 appsettings.Development.json
-rw-rw-r--. 1 cecuser cecuser 142 Jun 6 16:44 appsettings.json
drwxrwxr-x. 2 cecuser cecuser 24 Jun 6 16:44 Hubs
-rw-rw-r--. 1 cecuser cecuser 274 Jun 6 16:44 libman.json
drwxrwxr-x. 3 cecuser cecuser 205 Jun 6 16:44 Pages
IBM TechXchange 2024 / © 2024 IBM Corporation
21
-rw-rw-r--. 1 cecuser cecuser 430 Jun 6 16:44 Program.cs
drwxrwxr-x. 2 cecuser cecuser 33 Jun 6 16:44 Properties
-rw-rw-r--. 1 cecuser cecuser 210 Jun 6 16:44 SignalRChat.csproj
-rw-rw-r--. 1 cecuser cecuser 210 Jun 6 16:44 SignalRChat.csproj.ppc64le
-rw-rw-r--. 1 cecuser cecuser 475 Jun 6 16:44 SignalRChat.csproj.x86
drwxrwxr-x. 5 cecuser cecuser 57 Jun 6 16:44 wwwroot
SignalRChat/SignalRChat/Hubs:
total 4
-rw-rw-r--. 1 cecuser cecuser 274 Jun 6 16:44 ChatHub.cs
SignalRChat/SignalRChat/Pages:
total 32
-rw-rw-r--. 1 cecuser cecuser 856 Jun 6 16:44 Error.cshtml
-rw-rw-r--. 1 cecuser cecuser 708 Jun 6 16:44 Error.cshtml.cs
-rw-rw-r--. 1 cecuser cecuser 814 Jun 6 16:44 Index.cshtml
-rw-rw-r--. 1 cecuser cecuser 371 Jun 6 16:44 Index.cshtml.cs
-rw-rw-r--. 1 cecuser cecuser 164 Jun 6 16:44 Privacy.cshtml
-rw-rw-r--. 1 cecuser cecuser 378 Jun 6 16:44 Privacy.cshtml.cs
drwxrwxr-x. 2 cecuser cecuser 94 Jun 6 16:44 Shared
-rw-rw-r--. 1 cecuser cecuser 104 Jun 6 16:44 _ViewImports.cshtml
-rw-rw-r--. 1 cecuser cecuser 32 Jun 6 16:44 _ViewStart.cshtml
SignalRChat/SignalRChat/Pages/Shared:
total 12
-rw-rw-r--. 1 cecuser cecuser 2240 Jun 6 16:44 _Layout.cshtml
-rw-rw-r--. 1 cecuser cecuser 876 Jun 6 16:44 _Layout.cshtml.css
-rw-rw-r--. 1 cecuser cecuser 174 Jun 6 16:44 _ValidationScriptsPartial.cshtml
SignalRChat/SignalRChat/Properties:
total 4
-rw-rw-r--. 1 cecuser cecuser 876 Jun 6 16:44 launchSettings.json
SignalRChat/SignalRChat/wwwroot:
total 8
drwxrwxr-x. 2 cecuser cecuser 22 Jun 6 16:44 css
-rw-rw-r--. 1 cecuser cecuser 5430 Jun 6 16:44 favicon.ico
drwxrwxr-x. 3 cecuser cecuser 51 Jun 6 16:44 js
drwxrwxr-x. 6 cecuser cecuser 99 Jun 6 16:44 lib
SignalRChat/SignalRChat/wwwroot/css:
total 4
-rw-rw-r--. 1 cecuser cecuser 177 Jun 6 16:44 site.css
SignalRChat/SignalRChat/wwwroot/js:
total 8
-rw-rw-r--. 1 cecuser cecuser 1193 Jun 6 16:44 chat.js
drwxrwxr-x. 3 cecuser cecuser 18 Jun 6 16:44 signalr
-rw-rw-r--. 1 cecuser cecuser 226 Jun 6 16:44 site.js
SignalRChat/SignalRChat/wwwroot/js/signalr:
total 0
drwxrwxr-x. 3 cecuser cecuser 21 Jun 6 16:44 dist
SignalRChat/SignalRChat/wwwroot/js/signalr/dist:
total 0
drwxrwxr-x. 2 cecuser cecuser 46 Jun 6 16:44 browser
SignalRChat/SignalRChat/wwwroot/js/signalr/dist/browser:
total 184
-rw-rw-r--. 1 cecuser cecuser 139734 Jun 6 16:44 signalr.js
-rw-rw-r--. 1 cecuser cecuser 43394 Jun 6 16:44 signalr.min.js
IBM TechXchange 2024 / © 2024 IBM Corporation
22
SignalRChat/SignalRChat/wwwroot/lib:
total 0
drwxrwxr-x. 3 cecuser cecuser 33 Jun 6 16:44 bootstrap
drwxrwxr-x. 3 cecuser cecuser 37 Jun 6 16:44 jquery
drwxrwxr-x. 3 cecuser cecuser 36 Jun 6 16:44 jquery-validation
drwxrwxr-x. 2 cecuser cecuser 105 Jun 6 16:44 jquery-validation-unobtrusive
SignalRChat/SignalRChat/wwwroot/lib/bootstrap:
total 4
drwxrwxr-x. 4 cecuser cecuser 27 Jun 6 16:44 dist
-rw-rw-r--. 1 cecuser cecuser 1131 Jun 6 16:44 LICENSE
SignalRChat/SignalRChat/wwwroot/lib/bootstrap/dist:
total 8
drwxrwxr-x. 2 cecuser cecuser 4096 Jun 6 16:44 css
drwxrwxr-x. 2 cecuser cecuser 4096 Jun 6 16:44 js
SignalRChat/SignalRChat/wwwroot/lib/bootstrap/dist/css:
total 4896
-rw-rw-r--. 1 cecuser cecuser 204136 Jun 6 16:44 bootstrap.css
-rw-rw-r--. 1 cecuser cecuser 536547 Jun 6 16:44 bootstrap.css.map
-rw-rw-r--. 1 cecuser cecuser 70538 Jun 6 16:44 bootstrap-grid.css
-rw-rw-r--. 1 cecuser cecuser 196535 Jun 6 16:44 bootstrap-grid.css.map
-rw-rw-r--. 1 cecuser cecuser 51319 Jun 6 16:44 bootstrap-grid.min.css
-rw-rw-r--. 1 cecuser cecuser 117439 Jun 6 16:44 bootstrap-grid.min.css.map
-rw-rw-r--. 1 cecuser cecuser 70612 Jun 6 16:44 bootstrap-grid.rtl.css
-rw-rw-r--. 1 cecuser cecuser 196539 Jun 6 16:44 bootstrap-grid.rtl.css.map
-rw-rw-r--. 1 cecuser cecuser 51394 Jun 6 16:44 bootstrap-grid.rtl.min.css
-rw-rw-r--. 1 cecuser cecuser 117516 Jun 6 16:44 bootstrap-grid.rtl.min.css.map
-rw-rw-r--. 1 cecuser cecuser 162720 Jun 6 16:44 bootstrap.min.css
-rw-rw-r--. 1 cecuser cecuser 449111 Jun 6 16:44 bootstrap.min.css.map
-rw-rw-r--. 1 cecuser cecuser 5850 Jun 6 16:44 bootstrap-reboot.css
-rw-rw-r--. 1 cecuser cecuser 105138 Jun 6 16:44 bootstrap-reboot.css.map
-rw-rw-r--. 1 cecuser cecuser 4646 Jun 6 16:44 bootstrap-reboot.min.css
-rw-rw-r--. 1 cecuser cecuser 35330 Jun 6 16:44 bootstrap-reboot.min.css.map
-rw-rw-r--. 1 cecuser cecuser 5827 Jun 6 16:44 bootstrap-reboot.rtl.css
-rw-rw-r--. 1 cecuser cecuser 105151 Jun 6 16:44 bootstrap-reboot.rtl.css.map
-rw-rw-r--. 1 cecuser cecuser 4718 Jun 6 16:44 bootstrap-reboot.rtl.min.css
-rw-rw-r--. 1 cecuser cecuser 41570 Jun 6 16:44 bootstrap-reboot.rtl.min.css.map
-rw-rw-r--. 1 cecuser cecuser 203803 Jun 6 16:44 bootstrap.rtl.css
-rw-rw-r--. 1 cecuser cecuser 536461 Jun 6 16:44 bootstrap.rtl.css.map
-rw-rw-r--. 1 cecuser cecuser 162825 Jun 6 16:44 bootstrap.rtl.min.css
-rw-rw-r--. 1 cecuser cecuser 661035 Jun 6 16:44 bootstrap.rtl.min.css.map
-rw-rw-r--. 1 cecuser cecuser 71584 Jun 6 16:44 bootstrap-utilities.css
-rw-rw-r--. 1 cecuser cecuser 192271 Jun 6 16:44 bootstrap-utilities.css.map
-rw-rw-r--. 1 cecuser cecuser 53479 Jun 6 16:44 bootstrap-utilities.min.css
-rw-rw-r--. 1 cecuser cecuser 111875 Jun 6 16:44 bootstrap-utilities.min.css.map
-rw-rw-r--. 1 cecuser cecuser 71451 Jun 6 16:44 bootstrap-utilities.rtl.css
-rw-rw-r--. 1 cecuser cecuser 192214 Jun 6 16:44 bootstrap-utilities.rtl.css.map
-rw-rw-r--. 1 cecuser cecuser 53407 Jun 6 16:44 bootstrap-utilities.rtl.min.css
-rw-rw-r--. 1 cecuser cecuser 111710 Jun 6 16:44 bootstrap-utilities.rtl.min.css.map
SignalRChat/SignalRChat/wwwroot/lib/bootstrap/dist/js:
total 2440
-rw-rw-r--. 1 cecuser cecuser 208492 Jun 6 16:44 bootstrap.bundle.js
-rw-rw-r--. 1 cecuser cecuser 425643 Jun 6 16:44 bootstrap.bundle.js.map
-rw-rw-r--. 1 cecuser cecuser 78468 Jun 6 16:44 bootstrap.bundle.min.js
-rw-rw-r--. 1 cecuser cecuser 327261 Jun 6 16:44 bootstrap.bundle.min.js.map
-rw-rw-r--. 1 cecuser cecuser 139019 Jun 6 16:44 bootstrap.esm.js
-rw-rw-r--. 1 cecuser cecuser 288320 Jun 6 16:44 bootstrap.esm.js.map
-rw-rw-r--. 1 cecuser cecuser 72016 Jun 6 16:44 bootstrap.esm.min.js
-rw-rw-r--. 1 cecuser cecuser 222508 Jun 6 16:44 bootstrap.esm.min.js.map
-rw-rw-r--. 1 cecuser cecuser 148168 Jun 6 16:44 bootstrap.js
IBM TechXchange 2024 / © 2024 IBM Corporation
23
-rw-rw-r--. 1 cecuser cecuser 289522 Jun 6 16:44 bootstrap.js.map
-rw-rw-r--. 1 cecuser cecuser 59511 Jun 6 16:44 bootstrap.min.js
-rw-rw-r--. 1 cecuser cecuser 217145 Jun 6 16:44 bootstrap.min.js.map
SignalRChat/SignalRChat/wwwroot/lib/jquery:
total 4
drwxrwxr-x. 2 cecuser cecuser 66 Jun 6 16:44 dist
-rw-rw-r--. 1 cecuser cecuser 1605 Jun 6 16:44 LICENSE.txt
SignalRChat/SignalRChat/wwwroot/lib/jquery/dist:
total 508
-rw-rw-r--. 1 cecuser cecuser 287630 Jun 6 16:44 jquery.js
-rw-rw-r--. 1 cecuser cecuser 89476 Jun 6 16:44 jquery.min.js
-rw-rw-r--. 1 cecuser cecuser 137974 Jun 6 16:44 jquery.min.map
SignalRChat/SignalRChat/wwwroot/lib/jquery-validation:
total 4
drwxrwxr-x. 2 cecuser cecuser 124 Jun 6 16:44 dist
-rw-rw-r--. 1 cecuser cecuser 1095 Jun 6 16:44 LICENSE.md
SignalRChat/SignalRChat/wwwroot/lib/jquery-validation/dist:
total 136
-rw-rw-r--. 1 cecuser cecuser 42027 Jun 6 16:44 additional-methods.js
-rw-rw-r--. 1 cecuser cecuser 18464 Jun 6 16:44 additional-methods.min.js
-rw-rw-r--. 1 cecuser cecuser 48676 Jun 6 16:44 jquery.validate.js
-rw-rw-r--. 1 cecuser cecuser 23261 Jun 6 16:44 jquery.validate.min.js
SignalRChat/SignalRChat/wwwroot/lib/jquery-validation-unobtrusive:
total 32
-rw-rw-r--. 1 cecuser cecuser 19366 Jun 6 16:44 jquery.validate.unobtrusive.js
-rw-rw-r--. 1 cecuser cecuser 5868 Jun 6 16:44 jquery.validate.unobtrusive.min.js
-rw-rw-r--. 1 cecuser cecuser 575 Jun 6 16:44 LICENSE.txt
ls -l /home/cecuser/build
total 0
drwxrwxr-x. 5 cecuser cecuser 148 Jun 6 16:47 BlazorApp1
drwxrwxr-x. 7 cecuser cecuser 185 Jun 6 16:49 myMLApp
drwxrwxr-x. 5 cecuser cecuser 216 Jun 6 16:44 SignalRChat
drwxrwxr-x. 5 cecuser cecuser 218 Jun 6 16:45 stayingalive
5 Explore Quay.io
This part of the Lab will guide you through initial exploration of the Quay.io site.
You can watch a recording of this exercise
Explore the Quay.io site
- Navigate your browser to https://quay.io and spend a little time to navigate the site.
https://quay.io

- Select explore or follow the https://quay.io/search link and search for container images.
https://quay.io/search
- Search for anything you like, but here’s some ideas for you to try ppc64le, .net, dotnet, signalrchat, blazor1, stayingalive
https://quay.io/search?q=stayingalive

- There is also a specific Quay.io tutorial provided by Red Hat that you may follow when time allows. https://quay.io/tutorial/
https://quay.io/tutorial/

Pull .NET application containers from Quay.io to local Power server running RHEL
In this section we will pull .NET based application containers from the Quay.io registry.
- Look at Paul’s Quay.io repository, hosting .NET based containers used in this class. Note that I have created containers for both x86 and ppc64le, using the same source code.
https://quay.io/user/paulchapmanibm/

- Log into the bastion server using Putty, or favorite terminal as cecuser and change directory to the build directory
pwd
/home/cecuser
cd build
ls
BlazorApp1 myMLApp SignalRChat stayingalive
- You will find the docker and podman commands to pull a container from Quay.io in the container’s information area. We will use the podman command to pull the container images to our local Power server
https://quay.io/repository/paulchapmanibm/ppc64le/stayingalive

https://quay.io/repository/paulchapmanibm/ppc64le/signalrchat

https://quay.io/repository/paulchapmanibm/ppc64le/blazor1

- Copy, paste and execute each of the three podman commands from the relevant container image information areas to pull the container image to your server.
podman pull quay.io/paulchapmanibm/ppc64le/stayingalive
Trying to pull quay.io/paulchapmanibm/ppc64le/stayingalive:latest...
Getting image source signatures
Copying blob 88208a270532 done
Copying blob e99a72e50597 done
Copying blob d3ed8aa0df2d done
Copying blob ae222cd8449d done
Copying config b07b0d97a4 done
Writing manifest to image destination
Storing signatures
b07b0d97a4e418b4a89fb803387546538a8f45c918151b8c8907495ce8441098
podman pull quay.io/paulchapmanibm/ppc64le/signalrchat
Trying to pull quay.io/paulchapmanibm/ppc64le/signalrchat:latest...
Getting image source signatures
Copying blob e3cbbedef2d9 done
Copying blob ae222cd8449d skipped: already exists
Copying blob e99a72e50597 skipped: already exists
Copying blob d3ed8aa0df2d skipped: already exists
Copying config 9733a78ecb done
Writing manifest to image destination
Storing signatures
9733a78ecb79e58065c4c28ee12f5977138cc08c1679158991e480e4c47e8292
podman pull quay.io/paulchapmanibm/ppc64le/blazor1
Trying to pull quay.io/paulchapmanibm/ppc64le/blazor1:latest...
Getting image source signatures
Copying blob c5787e03b7df done
Copying blob ae222cd8449d skipped: already exists
Copying blob e99a72e50597 skipped: already exists
Copying blob d3ed8aa0df2d skipped: already exists
Copying config 4a74cdf9c4 done
Writing manifest to image destination
Storing signatures
- Confirm local access to the container images using the podman images command
podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
quay.io/paulchapmanibm/ppc64le/blazor1 latest 4a74cdf9c4ea 3 months ago 621 MB
quay.io/paulchapmanibm/ppc64le/stayingalive latest b07b0d97a4e4 3 months ago 629 MB
quay.io/paulchapmanibm/ppc64le/signalrchat latest 9733a78ecb79 5 months ago 629 MB
6 Explore Podman
Start and stop containers
In this section we will start and stop a container, recently pulled from Quay.io.
You can watch a recording of this exercise
- Confirm local access to the container images using the podman images command
podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
quay.io/paulchapmanibm/ppc64le/blazor1 latest 4a74cdf9c4ea 3 months ago 621 MB
quay.io/paulchapmanibm/ppc64le/stayingalive latest b07b0d97a4e4 3 months ago 629 MB
quay.io/paulchapmanibm/ppc64le/signalrchat latest 9733a78ecb79 5 months ago 629 MB
- Start one or more of the containers to run the .NET application
podman run blazor1
warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
Storing keys in a directory '/opt/app-root/.aspnet/DataProtection-Keys' that may not be
persisted outside of the container. Protected data will be unavailable when container is
destroyed.
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
No XML encryptor configured. Key {3d8e4a67-1017-4e69-a5b7-a0de5692bb59} may be
persisted to storage in unencrypted form.
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://[::]:8080
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
Content root path: /opt/app-root/app
- Now stop the container with CTRL +C
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://[::]:8080
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
IBM TechXchange 2024 / © 2024 IBM Corporation
31
Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
Content root path: /opt/app-root/app
^Cinfo: Microsoft.Hosting.Lifetime[0]
Application is shutting down...
- Confirm local access to the container images using the podman images command
podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
quay.io/paulchapmanibm/ppc64le/blazor1 latest 4a74cdf9c4ea 3 months ago 621 MB
quay.io/paulchapmanibm/ppc64le/stayingalive latest b07b0d97a4e4 3 months ago 629 MB
quay.io/paulchapmanibm/ppc64le/signalrchat latest 9733a78ecb79 5 months ago 629 MB
Remove container images using podman
In this section we will remove the previously obtained container images using the podman command.
- Identify the containers to remove using the podman images command. Note the IMAGE ID of each container.
podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
quay.io/paulchapmanibm/ppc64le/blazor1 latest 4a74cdf9c4ea 3 months ago 621 MB
quay.io/paulchapmanibm/ppc64le/stayingalive latest b07b0d97a4e4 3 months ago 629 MB
quay.io/paulchapmanibm/ppc64le/signalrchat latest 9733a78ecb79 5 months ago 629 MB
- Now remove the container images using the podman command. Note that the ID’s for your containers may be different, and that I have forced the removal of multiple containers at the same time in the example below
podman rmi <add_your-id> <add_your-id> <add_your-id> -f
Example:
podman rmi 4a74cdf9c4ea b07b0d97a4e4 9733a78ecb79 -f
Untagged: quay.io/paulchapmanibm/ppc64le/blazor1:latest
Untagged: quay.io/paulchapmanibm/ppc64le/stayingalive:latest
Untagged: quay.io/paulchapmanibm/ppc64le/signalrchat:latest
Deleted: 4a74cdf9c4ead4056e21633db16ff26b40eced1f0bfb6b3803141d9a30c2e53e
Deleted: b07b0d97a4e418b4a89fb803387546538a8f45c918151b8c8907495ce8441098
Deleted: 9733a78ecb79e58065c4c28ee12f5977138cc08c1679158991e480e4c47e8292
- Confirm the containers are no longer available
podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
7 Deploy Message App Manually
This part of the lab will guide you through process of cloning the code hosted on GitHub, inspecting the files to understand how the code is organized to build container images. This part of the lab will be completed using the user “cecuser”.
You can watch a recording of this exercise
Obtain the dotnet container image
Quay.io is a registry for storing and building container images as well as distributing other OCI artifacts.
- Check you have the correct user. The whoami command should return cecuser
whoami
cecuser
- Obtain the dotnet image from Quay.io registry
podman pull quay.io/paulchapmanibm/ppc64le/dotnet-70
Trying to pull quay.io/paulchapmanibm/ppc64le/dotnet-70:latest...
Getting image source signatures
Copying blob ae222cd8449d done |
Copying blob d3ed8aa0df2d done |
Copying blob e99a72e50597 done |
Copying config f579cd2fc8 done |
Writing manifest to image destination
f579cd2fc8b3b2cccf68aea14afb1b04770bda24d4de5e395031a278f3e6283a
Clone ASP & SignalR application source from GitHub
- Create a build directory. It’s fine if the directory already exists
mkdir /home/cecuser/build
- Change to the newly created Directory
cd /home/cecuser/build
- Check you are on the correct Directory
sudo dnf install git
- Install git. It’s fine if already installed
$ Is this ok [y/N]:
Y
- Clone the application source from github
git clone https://github.com/paulchapmanibm/SignalRchat.git
Cloning into 'SignalRchat'...
remote: Enumerating objects: 158, done.
remote: Counting objects: 100% (158/158), done.
remote: Compressing objects: 100% (104/104), done.
remote: Total 158 (delta 60), reused 139 (delta 46), pack-reused 0 (from 0)
Receiving objects: 100% (158/158), 906.94 KiB | 13.95 MiB/s, done.
Resolving deltas: 100% (60/60), done.
- You should see a new folder created
ls -la
total 16
drwxr-xr-x. 7 cecuser cecuser 97 Dec 20 06:01 .
drwx------. 14 cecuser cecuser 4096 Dec 20 05:49 ..
drwxr-xr-x. 5 cecuser cecuser 4096 Dec 20 06:01 SignalRchat
Build the application container, for use on Power
- Change to the new application directory
cd /home/cecuser/build/SignalRchat
- Copy the ppc64le dockerfile, which will be used to build the application container. Note I include one for ppc64le and another for x86. Compare the two with the diff command if you like.
cp Dockerfile.ppc64le Dockerfile
- Copy the ppc64le csproj file, which will be used to build the application container. Take a look but don’t change anything. Again, I provide one for x86 and another for ppc64le. Run a diff on the two files if you like. I simply use .NET 7, rather than .NET 6 for ppc64le.
cp ./SignalRChat/SignalRChat.csproj.ppc64le/SignalRChat/SignalRChat.csproj
- Build the application container using Podman
podman build . -t signalrchat
[2/4] STEP 1/8: FROM dotnet-70 AS build
[2/4] STEP 2/8: WORKDIR /src
--> 515aad83b66c
[2/4] STEP 3/8: COPY --chown=1001 ["SignalRChat/SignalRChat.csproj", "SignalRChat/"]
--> 9aee5688368d
[2/4] STEP 4/8: RUN dotnet restore "SignalRChat/SignalRChat.csproj"
Determining projects to restore...
Restored /src/SignalRChat/SignalRChat.csproj (in 147 ms).
--> 0ee5a49e91a2
[2/4] STEP 5/8: COPY --chown=1001 . ./
--> 66617d4073f1
[2/4] STEP 6/8: WORKDIR "/src/SignalRChat"
--> 4b1254dd191b
[2/4] STEP 7/8: USER root
--> ecaa6eda3da6
[2/4] STEP 8/8: RUN dotnet build "SignalRChat.csproj" -c Release -o /app/build
MSBuild version 17.4.0+18d5aef85 for .NET
Determining projects to restore...
All projects are up-to-date for restore.
SignalRChat -> /app/build/SignalRChat.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:10.00
--> df54899c921d
[3/4] STEP 1/2: FROM df54899c921dffc3f5f5bea1cee4c1b57934bbae1c05529e5d5963dccc058f76 AS publish
[3/4] STEP 2/2: RUN dotnet publish "SignalRChat.csproj" -c Release -o /app/publish /p:UseAppHost=false
MSBuild version 17.4.0+18d5aef85 for .NET
Determining projects to restore...
All projects are up-to-date for restore.
SignalRChat -> /src/SignalRChat/bin/Release/net7.0/SignalRChat.dll
SignalRChat -> /app/publish/
--> b4d2398e6117
[4/4] STEP 1/4: FROM dotnet-70 AS final
[4/4] STEP 2/4: WORKDIR /app
--> 705ddd7c3d30
[4/4] STEP 3/4: COPY --chown=1001 --from=publish /app/publish .
--> 23c7fd957c8c
[4/4] STEP 4/4: ENTRYPOINT ["dotnet", "SignalRChat.dll"]
[4/4] COMMIT signalrchat
--> ea3406e5cdcd
Successfully tagged localhost/signalrchat:latest
ea3406e5cdcdadbee74e8c22bb4cb21441bd1bfde8e0b3e1b24739cd81e40d36
- Confirm that both dotnet and application containers are available.
podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> b4d2398e6117 40 seconds ago 648 MB
localhost/signalrchat latest ea3406e5cdcd 40 seconds ago 629 MB
quay.io/paulchapmanibm/ppc64le/dotnet-70 latest f579cd2fc8b3 2 years ago 621 MB
Create New Project & Transfer Container to OCP registry
- Login to OCP as the cecuser user
oc login -u cecuser
Logged into "https://api.p1324.cecc.ihost.com:6443" as "cecuser" using existing credentials.
You have access to 71 projects, the list has been suppressed. You can list all projects with 'oc projects'
Using project "default".
By default, the OpenShift Container Platform registry is secured during cluster installation so that it serves traffic through TLS. Unlike previous versions of OpenShift Container Platform, the registry is not exposed outside of the cluster at the time of installation.
- Expose the OCP default registry.
REGHOST=`oc get route default-route -n openshift-image-registry --template='{{ .spec.host }}'`
- Check the variable has been set correctly. You may need to ensure that you are still logged into OpenShift via the command line interface, as carried out in chapter 2. The variable should be similar, but different to the below. If not, then log back into OpenShift using the oc login command with your token as described in chapter 2.
echo $REGHOST
default-route-openshift-image-registry.apps.p1324.cecc.ihost.com
- Login to the OCP default registry
podman login --tls-verify=false -u cecuser -p $(oc whoami -t) ${REGHOST}
Login Succeeded!
- Create new OCP namespace for the application
oc new-project signalrchat
Now using project "signalrchat" on server "https://api.p1324.cecc.ihost.com:6443".
You can add applications to this project with the 'new-app' command. For example, try:
oc new-app rails-postgresql-example
to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:
kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.43 -- /agnhost serve-hostname
- Push the application container into the OCP default registry
podman push --tls-verify=false $(podman images | grep signalrchat | awk '{print $3}') $REGHOST/signalrchat/signalrchat
Getting image source signatures
Copying blob f8d00697cd3d done |
Copying blob c34048e29ca6 done |
Copying blob c38c6791c82e done |
Copying blob 669f475e58c3 done |
Copying config ea3406e5cd done |
Writing manifest to image destination
Create and expose OCP application
- Create the new OCP application expose (create external route to) the application.
oc new-app --image-stream=signalrchat
--> Found image ea3406e (11 minutes old) in image stream "signalrchat/signalrchat" under tag "latest" for "signalrchat"
.NET 7
------
Platform for building and running .NET 7 applications
Tags: builder, .net, dotnet, dotnetcore, dotnet-70
--> Creating resources ...
deployment.apps "signalrchat" created
service "signalrchat" created
--> Success
Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
'oc expose service/signalrchat'
Run 'oc status' to view your app.
- Expose (create external route to) the new OCP application
oc expose service/signalrchat
route/signalrchat exposed
Obtain the application URL
- Obtain the application Url, (your url will be different to that shown below)
oc status | grep 8080 | awk '{print $1}'
Warning: apps.openshift.io/v1 DeploymentConfig is deprecated in v4.14+, unavailable in v4.10000+
http://signalrchat-signalrchat.apps.p1324.cecc.ihost.com
Start Web Browsers and send messages
- Start multiple browsers, size and position them so you can see them all at same time. I have used Firefox, Chrome and Edge browsers for this demonstration, but you may use any number of alternatives.

- Copy the URL obtained from 3. Section 1, and paste into each browser. Remember that the URL for your application will be different from the example below.

- Enter username and message into the first browser and click “Send Message” button
IBM says:

- Continue entering and sending messages as desired
Red Hat says:

IBM says:

Microsoft says:

Cleanup SignalRChat deployment
- Ensure you are logged in to OpenShift as cecuser
oc login -u cecuser
Logged into "https://api.p1382.cecc.ihost.com:6443" as "cecuser" using existing credentials.
You have access to 71 projects, the list has been suppressed. You can list all projects with
'oc projects'
Using project "signalrchat".
- Remove Git – Optional
sudo dnf remove git
Updating Subscription Management repositories.
Dependencies resolved.
======================================================================================================================
Package Architecture Version Repository Size
======================================================================================================================
Removing:
git ppc64le 2.39.3-1.el8_8 @rhel-8-for-ppc64le-appstream-rpms 133 k
IBM TechXchange 2024 / © 2024 IBM Corporation
43
Removing unused dependencies:
git-core ppc64le 2.39.3-1.el8_8 @rhel-8-for-ppc64le-appstream-rpms 39 M
git-core-doc noarch 2.39.3-1.el8_8 @rhel-8-for-ppc64le-appstream-rpms 14 M
perl-Error noarch 1:0.17025-2.el8 @rhel-8-for-ppc64le-appstream-rpms 70 k
perl-Git noarch 2.39.3-1.el8_8 @rhel-8-for-ppc64le-appstream-rpms 65 k
perl-TermReadKey ppc64le 2.37-7.el8 @rhel-8-for-ppc64le-appstream-rpms 108 k
Transaction Summary
======================================================================================================================
Remove 6 Packages
Freed space: 53 M
Is this ok [y/N]: y
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Erasing : git-2.39.3-1.el8_8.ppc64le 1/6
Erasing : git-core-doc-2.39.3-1.el8_8.noarch 2/6
Erasing : perl-Git-2.39.3-1.el8_8.noarch 3/6
Erasing : perl-Error-1:0.17025-2.el8.noarch 4/6
Erasing : git-core-2.39.3-1.el8_8.ppc64le 5/6
Erasing : perl-TermReadKey-2.37-7.el8.ppc64le 6/6
Running scriptlet: perl-TermReadKey-2.37-7.el8.ppc64le 6/6
Verifying : git-2.39.3-1.el8_8.ppc64le 1/6
Verifying : git-core-2.39.3-1.el8_8.ppc64le 2/6
Verifying : git-core-doc-2.39.3-1.el8_8.noarch 3/6
Verifying : perl-Error-1:0.17025-2.el8.noarch 4/6
Verifying : perl-Git-2.39.3-1.el8_8.noarch 5/6
Verifying : perl-TermReadKey-2.37-7.el8.ppc64le 6/6
Installed products updated.
Removed:
git-2.39.3-1.el8_8.ppc64le git-core-2.39.3-1.el8_8.ppc64le git-core-doc-2.39.3-1.el8_8.noarch
perl-Error-1:0.17025-2.el8.noarch perl-Git-2.39.3-1.el8_8.noarch perl-TermReadKey-2.37-7.el8.ppc64le
Complete!
- Delete the signalrchat project
oc delete project signalrchat
Project.project.openshift.io "signalrchat" deleted
- Remove the project directory
cd ..; rm -rdf /home/cecuser/build/SignalRchat
- Remove the container images.
for i in $(podman images | grep -E "dotnet-70|signalrchat|none" | grep -v "IMAGE" | awk '{print $3}')
(Press Enter/Return, then the following four commands to complete the loop)
do
podman rmi $i -f
done
Untagged: localhost/signalrchat:latest
Deleted: 05a243df6ce2490106170e3d7f3aa3f3ff8df5350bd70c663578b75680d93a38
Deleted: 1f0b2ff28347c0964d0748f8ea6bf8411d11fe8d933aaa3e89797879aa251efe
Deleted: 5a401155fe567b4203174d9a2d69569f4a6ec535e90fb307bca4b4f7b3fc5abb
Deleted: dd0cf37540fb39fcb0f7056a16ef700cf3df6a7f33bd1e3cefd8c29909321c95
Deleted: 6d0a1afe8a9b05e3174e178c780c1c7e087a20f745088f47e9b48647706d63c6
Deleted: a115b350501bddb210dd91d1868ee769a130fd0ba2327515f0c2609ecc6e0cfd
Deleted: d714fc70e7afa346d5103b5de4a5abe85fd06f8ae3d3f0fb0ee815c60b67dbae
Deleted: 62476fee74ee15ff4ae6b3a3172621100198dbb9ceab74d77dc2343cd0f41f3d
Deleted: 925b7c0cd37669e82d1d72d719265588755f43ca84d6d1a98e572b07b8572995
Deleted: 29492640f6bf49dadecd41076f8bcc738b9542347b58973c0f77f3e15c8b9fb5
Deleted: 6f0edee35c6313272107cca81bcf60ecf4c50ff292f597fe6959a49f35fcf0cd
Untagged: quay.io/paulchapmanibm/ppc64le/dotnet-70:latest
Deleted: f579cd2fc8b3b2cccf68aea14afb1b04770bda24d4de5e395031a278f3e6283a
podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
8 Deploy Message App with S2I
This part of the lab will guide you through process of creating a new project, cloning the code hosted on GitHub, and building the .Net application using S2I. This part of the lab will be completed using the cecuser user.
You can watch a recording of the exercise
Deploy the application using Source to Image
- Log in to the TechZone OCP using a browser as user, cecuser


- Switch to Developer view


- Open the “Project: All Projects” drop down list and create new “signalrchat” project


- Select “+ Add”, and “Import from Git”


- Go to https://github.com/paulchapmanibm/SignalRChat using another browser window or tab, then select the “<> Code button and copy the url that points to the application source code using HTTPS. This is where OCP will clone the source code from when building the application container image later.
https://github.com/paulchapmanibm/SignalRChat.git

- Return to the OCP Console browser window or tab and paste the url copied from above step into the Git Repo URL field. Notice the new Validated notice underneath.

- Now, left click on “Edit Import Strategy”, followed by “Builder Image” buttons


- Select .Net when you are presented with a list of available Builder Images. You previously added the “.Net” option at “2. Section 1 Add the .net Builder Image”

- Scroll down and select Builder Image version ‘IST 7.0-ubi8’

- Scroll down and left click Create Image

- You will see the application resource added to the projects Topology. Notice the light blue circle around the .NET logo, which means that the application/container is being built.

- If you are quick, you can select the Build icon, which shows you the logs during the build. If you are not so quick, you will still see and be able to scroll through the build log.


- Once the build is complete, select “Topology” and you will see that the previous light blue circle has now turned dark blue, which indicates the build has completed.


- Clicking on the “Open url” icon will open a browser to the application front end.


Start Web Browsers and send messages
- Start multiple browsers, size and position them so you can see them all at same time. I have used Firefox, Chrome and Edge browsers for this demonstration, but you may use any number of alternatives.

- Copy the URL obtained from 3. Section 1 and paste into each browser. Remember that the URL for your application will be different from the example below.

- Enter username and message into the first browser and click “Send Message” button.
IBM says

- Continue entering and sending messages as desired.
Red Hat says:

IBM says:

Microsoft says:

Remove signalrchat project
- Select the Developer view Project, Actions and Delete Project

- Enter the project name, signalrchat and click delete. That was easier, wasn’t it 😊

9 Deploy Website with ASP.Net Core & Blazor
This lab will guide you through process of creating a new project, cloning the code hosted on GitHub, and building the .Net application using S2I via command line interface. This lab will be completed using the cecuser user.
You can watch a recording of this exercise
Add the .Net Builder image
Follow the below steps to add the .Net 7 builder image to OCP.
- Log in to the OCP Bastion Server as the cecuser. Check you have the correct user. The whoami command should return cecuser.
whoami
cecuser
- Switch to the openshift project
oc project openshift
Logged into "https://api.p1324.cecc.ihost.com:6443" as "cecuser" using the token provided.
You have access to 71 projects, the list has been suppressed. You can list all projects with 'oc projects'
Using project "openshift".
[cecuser@p1324-bastion ~]$ whoami
cecuser
[cecuser@p1324-bastion ~]$ oc project openshift
Already on project "openshift" on server "https://api.p1324.cecc.ihost.com:6443".
Deploy the application using Source to Image
- Log into the OCP RHEL Bastion using cecuser credentials and install git command line interface
sudo dnf install git
Updating Subscription Management repositories.
Last metadata expiration check: 0:41:26 ago on Fri 20 Dec 2024 07:00:21 AM EST.
Dependencies resolved.
================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
git ppc64le 2.43.5-2.el9_5 rhel-9-for-ppc64le-appstream-rpms 54 k
Installing dependencies:
emacs-filesystem
noarch 1:27.2-10.el9_4 rhel-9-for-ppc64le-appstream-rpms 9.3 k
git-core ppc64le 2.43.5-2.el9_5 rhel-9-for-ppc64le-appstream-rpms 4.8 M
git-core-doc noarch 2.43.5-2.el9_5 rhel-9-for-ppc64le-appstream-rpms 2.9 M
perl-DynaLoader
ppc64le 1.47-481.el9 rhel-9-for-ppc64le-appstream-rpms 26 k
perl-Error noarch 1:0.17029-7.el9 rhel-9-for-ppc64le-appstream-rpms 46 k
perl-File-Find noarch 1.37-481.el9 rhel-9-for-ppc64le-appstream-rpms 26 k
perl-Git noarch 2.43.5-2.el9_5 rhel-9-for-ppc64le-appstream-rpms 39 k
perl-TermReadKey
ppc64le 2.38-11.el9 rhel-9-for-ppc64le-appstream-rpms 41 k
Transaction Summary
================================================================================
Install 9 Packages
Total size: 8.0 M
Installed size: 41 M
Is this ok [y/N]: y
Downloading Packages:
[SKIPPED] perl-Error-0.17029-7.el9.noarch.rpm: Already downloaded
[SKIPPED] perl-TermReadKey-2.38-11.el9.ppc64le.rpm: Already downloaded
[SKIPPED] perl-DynaLoader-1.47-481.el9.ppc64le.rpm: Already downloaded
[SKIPPED] perl-File-Find-1.37-481.el9.noarch.rpm: Already downloaded
[SKIPPED] emacs-filesystem-27.2-10.el9_4.noarch.rpm: Already downloaded
[SKIPPED] git-2.43.5-2.el9_5.ppc64le.rpm: Already downloaded
[SKIPPED] git-core-2.43.5-2.el9_5.ppc64le.rpm: Already downloaded
[SKIPPED] git-core-doc-2.43.5-2.el9_5.noarch.rpm: Already downloaded
[SKIPPED] perl-Git-2.43.5-2.el9_5.noarch.rpm: Already downloaded
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : git-core-2.43.5-2.el9_5.ppc64le 1/9
Installing : git-core-doc-2.43.5-2.el9_5.noarch 2/9
Installing : emacs-filesystem-1:27.2-10.el9_4.noarch 3/9
Installing : perl-File-Find-1.37-481.el9.noarch 4/9
Installing : perl-DynaLoader-1.47-481.el9.ppc64le 5/9
Installing : perl-TermReadKey-2.38-11.el9.ppc64le 6/9
Installing : perl-Error-1:0.17029-7.el9.noarch 7/9
Installing : git-2.43.5-2.el9_5.ppc64le 8/9
Installing : perl-Git-2.43.5-2.el9_5.noarch 9/9
Running scriptlet: perl-Git-2.43.5-2.el9_5.noarch 9/9
Verifying : perl-Error-1:0.17029-7.el9.noarch 1/9
Verifying : perl-TermReadKey-2.38-11.el9.ppc64le 2/9
Verifying : perl-DynaLoader-1.47-481.el9.ppc64le 3/9
Verifying : perl-File-Find-1.37-481.el9.noarch 4/9
Verifying : emacs-filesystem-1:27.2-10.el9_4.noarch 5/9
Verifying : git-2.43.5-2.el9_5.ppc64le 6/9
Verifying : git-core-2.43.5-2.el9_5.ppc64le 7/9
Verifying : git-core-doc-2.43.5-2.el9_5.noarch 8/9
Verifying : perl-Git-2.43.5-2.el9_5.noarch 9/9
Installed products updated.
Installed:
emacs-filesystem-1:27.2-10.el9_4.noarch git-2.43.5-2.el9_5.ppc64le
git-core-2.43.5-2.el9_5.ppc64le git-core-doc-2.43.5-2.el9_5.noarch
perl-DynaLoader-1.47-481.el9.ppc64le perl-Error-1:0.17029-7.el9.noarch
perl-File-Find-1.37-481.el9.noarch perl-Git-2.43.5-2.el9_5.noarch
perl-TermReadKey-2.38-11.el9.ppc64le
Complete!
- Create new OpenShift Project
oc new-project blazorapp1 --description="Simple .NET example using Blazor with Power" --display-name="blazorapp1"
Now using project "blazorapp1" on server "https://api.p1324.cecc.ihost.com:6443".
You can add applications to this project with the 'new-app' command. For example, try:
oc new-app rails-postgresql-example
to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:
kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.43 -- /agnhost serve-hostname
- Create the application
oc new-app --image-stream="openshift/dotnet:7.0-ubi8"~https://github.com/paulchapmanibm/BlazorApp1.git
--> Found image a570ba8 (6 months old) in image stream "openshift/dotnet" under tag "7.0-ubi8" for "openshift/dotnet:7.0-ubi8"
.NET 7
------
Platform for building and running .NET 7 applications
Tags: builder, .net, dotnet, dotnetcore, dotnet-70
* A source build using source code from https://github.com/paulchapmanibm/BlazorApp1.git will be created
* The resulting image will be pushed to image stream tag "blazorapp1:latest"
* Use 'oc start-build' to trigger a new build
--> Creating resources ...
imagestream.image.openshift.io "blazorapp1" created
buildconfig.build.openshift.io "blazorapp1" created
deployment.apps "blazorapp1" created
service "blazorapp1" created
--> Success
Build scheduled, use 'oc logs -f buildconfig/blazorapp1' to track its progress.
Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
'oc expose service/blazorapp1'
Run 'oc status' to view your app.
- Track the progress of the build
oc logs -f buildconfig/blazorapp1
Cloning "https://github.com/paulchapmanibm/BlazorApp1.git" ...
Commit: 0a6979a044c27b12a5dda800fb71bec86b36e590 (Update Dockerfile.ppc64le)
Author: Paul Chapman <paulchapman@uk.ibm.com>
Date: Thu Dec 22 19:40:51 2022 +0000
time="2024-12-20T12:43:02Z" level=info msg="Not using native diff for overlay, this may cause degraded performance for building images: kernel has CONFIG_OVERLAY_FS_REDIRECT_DIR enabled"
I1220 12:43:02.806910 1 defaults.go:112] Defaulting to storage driver "overlay" with options [mountopt=metacopy=on].
Caching blobs under "/var/cache/blobs".
Trying to pull image-registry.openshift-image-registry.svc:5000/openshift/dotnet@sha256:a00254763ebe989e70df3fce146edd5a46eb0a84c103c4e3fcad52e2dcde450b...
Getting image source signatures
Copying blob sha256:cbc66c19910e3c1532b3ed790e2c46ff551ef718b378aeaa163643db9af77b30
Copying blob sha256:02821430ac1875e4cc0ff7f0b59484161bc05db0822a68ebed0630ec94cca2c7
Copying blob sha256:abfba1df8b7596a37fa71d2279323b21eeb9fdf171adbc929573e212afde27fc
Copying config sha256:a570ba8238bef09096bd998f2b6c980feb47ff063c31a5e7a4ff9b552f008592
Writing manifest to image destination
Generating dockerfile with builder image image-registry.openshift-image-registry.svc:5000/openshift/dotnet@sha256:a00254763ebe989e70df3fce146edd5a46eb0a84c103c4e3fcad52e2dcde450b
Adding transient rw bind mount for /run/secrets/rhsm
STEP 1/9: FROM image-registry.openshift-image-registry.svc:5000/openshift/dotnet@sha256:a00254763ebe989e70df3fce146edd5a46eb0a84c103c4e3fcad52e2dcde450b
STEP 2/9: LABEL "io.openshift.build.source-location"="https://github.com/paulchapmanibm/BlazorApp1.git" "io.openshift.build.image"="image-registry.openshift-image-registry.svc:5000/openshift/dotnet@sha256:a00254763ebe989e70df3fce146edd5a46eb0a84c103c4e3fcad52e2dcde450b" "io.openshift.build.commit.author"="Paul Chapman <paulchapman@uk.ibm.com>" "io.openshift.build.commit.date"="Thu Dec 22 19:40:51 2022 +0000" "io.openshift.build.commit.id"="0a6979a044c27b12a5dda800fb71bec86b36e590" "io.openshift.build.commit.ref"="master" "io.openshift.build.commit.message"="Update Dockerfile.ppc64le"
STEP 3/9: ENV DOTNET_STARTUP_PROJECT="BlazorApp1/BlazorApp1.csproj" OPENSHIFT_BUILD_NAME="blazorapp1-1" OPENSHIFT_BUILD_NAMESPACE="blazorapp1" OPENSHIFT_BUILD_SOURCE="https://github.com/paulchapmanibm/BlazorApp1.git" OPENSHIFT_BUILD_COMMIT="0a6979a044c27b12a5dda800fb71bec86b36e590"
STEP 4/9: USER root
STEP 5/9: COPY upload/src /tmp/src
STEP 6/9: RUN chown -R 1001:0 /tmp/src
STEP 7/9: USER 1001
STEP 8/9: RUN /usr/libexec/s2i/assemble
---> Installing application source...
Using SDK: 7.0.119
---> Restoring application dependencies...
Determining projects to restore...
Restored /opt/app-root/src/BlazorApp1/BlazorApp1.csproj (in 1.38 sec).
---> Publishing application...
MSBuild version 17.4.8+6918b863a for .NET
BlazorApp1 -> /opt/app-root/src/BlazorApp1/bin/Release/net7.0/BlazorApp1.dll
BlazorApp1 -> /opt/app-root/app/
STEP 9/9: CMD /usr/libexec/s2i/run
COMMIT temp.builder.openshift.io/blazorapp1/blazorapp1-1:490e13ee
time="2024-12-20T12:43:25Z" level=warning msg="archive: skipping \"/var/lib/containers/storage/overlay/7379dad0c855850c43cdcdf46f197876aa14af2ceeb3ad7c218cb62a59ddf686/merged/tmp/_f7KucZirGgg2dsv9fzkypOiyT+0Ds5wYg0teFehqcM\" since it is a socket"
time="2024-12-20T12:43:25Z" level=warning msg="archive: skipping \"/var/lib/containers/storage/overlay/7379dad0c855850c43cdcdf46f197876aa14af2ceeb3ad7c218cb62a59ddf686/merged/tmp/dotnet-diagnostic-84-9362357-socket\" since it is a socket"
Getting image source signatures
Copying blob sha256:87bb6c622b3397c1ff23f61d7e37a21632d34adc76a83a6a79ac950a7a198d7c
Copying blob sha256:b5c318a41ced1ded48a9637793eeb005d1f79fc8292fe6975531fc933a012ac0
Copying blob sha256:2a6a4ea6b3489ca5f7d62e548f3c4b5de84c8e6a7797bb11f4c83540a240b788
Copying blob sha256:5b2f1e46642c690c2340dbf323d676a333395a916985d7521420f09e481fd2f9
Copying config sha256:26b0f0bf2ebe7a1a782bae54bee32849f21398cb38048b3acb8b6d4ba11f1e62
Writing manifest to image destination
--> 26b0f0bf2ebe
Successfully tagged temp.builder.openshift.io/blazorapp1/blazorapp1-1:490e13ee
26b0f0bf2ebe7a1a782bae54bee32849f21398cb38048b3acb8b6d4ba11f1e62
Pushing image image-registry.openshift-image-registry.svc:5000/blazorapp1/blazorapp1:latest ...
Getting image source signatures
Copying blob sha256:5b2f1e46642c690c2340dbf323d676a333395a916985d7521420f09e481fd2f9
Copying blob sha256:cbc66c19910e3c1532b3ed790e2c46ff551ef718b378aeaa163643db9af77b30
Copying blob sha256:02821430ac1875e4cc0ff7f0b59484161bc05db0822a68ebed0630ec94cca2c7
Copying blob sha256:abfba1df8b7596a37fa71d2279323b21eeb9fdf171adbc929573e212afde27fc
Copying config sha256:26b0f0bf2ebe7a1a782bae54bee32849f21398cb38048b3acb8b6d4ba11f1e62
Writing manifest to image destination
Successfully pushed image-registry.openshift-image-registry.svc:5000/blazorapp1/blazorapp1@sha256:44bae6e8aae67e399c33a83ab36169254a0610b3cfbe48965429a64b81c3baf6
Push successful
- Once the build is complete and the resulting image has successfully pushed to your registry, check the status of your application:
oc status
Warning: apps.openshift.io/v1 DeploymentConfig is deprecated in v4.14+, unavailable in v4.10000+
In project blazorapp1 on server https://api.p1324.cecc.ihost.com:6443
svc/blazorapp1 - 172.30.35.196:8080
deployment/blazorapp1 deploys istag/blazorapp1:latest <-
bc/blazorapp1 source builds https://github.com/paulchapmanibm/BlazorApp1.git on openshift/dotnet:7.0-ubi8
deployment #2 running for 2 minutes - 1 pod
deployment #1 deployed 3 minutes ago
1 info identified, use 'oc status --suggest' to see details.
- Create a Route. An OpenShift Container Platform route exposes a service at a host name, so that external clients can reach it by name. To create an external route to your new application, expose the application service.
oc expose service blazorapp1
route/blazorapp1 exposed
- View your new route
oc get route
NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
blazorapp1 blazorapp1-blazorapp1.apps.p1324.cecc.ihost.com blazorapp1 8080-tcp None
Verify and test the application
- Verify the Application is Running. To view your new application, paste the application route URL into the address bar of your web browser and hit enter.
echo "The url to your new application is $(oc status | grep "http://blazorapp1-blazorapp1" | awk '{print $1}')"
Warning: apps.openshift.io/v1 DeploymentConfig is deprecated in v4.14+, unavailable in v4.10000+
The url to your new application is http://blazorapp1-blazorapp1.apps.p1324.cecc.ihost.com

- Increase the counter by clicking the “Click me” button. Notice the increment of 10 each click.

- Select + Counter from the left side menu to see another counter.

- Click this other “Click me” button to increment counter by 1 each click.

- Return to the “Home” page

- Click the “brief survey” link to complete the survey

Remove the Blazor project
- Remove the Blazor project.
oc delete project blazorapp1
project.project.openshift.io "blazorapp1" deleted
10 Deploy the .NET game using Shift tool
This part of the demo will guide you through process of creating a new project and building the .Net based game using the dotnet Shift tool available from https://github.com/paulchapmanibm/dotnet-shift
This part of the demo will be completed using the cecuser user.
You can watch a recording of this exercise
Install/provide prerequisites
Follow the below steps to add the .Net 7 builder image to OCP.
- Log in to the OCP Bastion Server as the cecuser. Check you have the correct user. The whoami command should return cecuser.
whoami
cecuser
- Change to the build directory.
cd /home/cecuser/build
- Install/update Git.
sudo dnf install git
Updating Subscription Management repositories.
Red Hat Enterprise Linux 8 for Power, little endian - Supplementary (RPMs) 83 kB/s | 3.8 kB 00:00
Red Hat Enterprise Linux 8 for Power, little endian - AppStream (RPMs) 69 kB/s | 2.9 kB 00:00
Red Hat Enterprise Linux 8 for Power, little endian - BaseOS (RPMs) 105 kB/s | 4.1 kB 00:00
Dependencies resolved.
======================================================================================================================
Package Architecture Version Repository Size
======================================================================================================================
Installing:
git ppc64le 2.39.3-1.el8_8 rhel-8-for-ppc64le-appstream-rpms 104 k
Installing dependencies:
git-core ppc64le 2.39.3-1.el8_8 rhel-8-for-ppc64le-appstream-rpms 12 M
git-core-doc noarch 2.39.3-1.el8_8 rhel-8-for-ppc64le-appstream-rpms 3.0 M
perl-Error noarch 1:0.17025-2.el8 rhel-8-for-ppc64le-appstream-rpms 46 k
perl-Git noarch 2.39.3-1.el8_8 rhel-8-for-ppc64le-appstream-rpms 79 k
perl-TermReadKey ppc64le 2.37-7.el8 rhel-8-for-ppc64le-appstream-rpms 42 k
Transaction Summary
======================================================================================================================
Install 6 Packages
Total download size: 15 M
Installed size: 53 M
Is this ok [y/N]: y
Downloading Packages:
(1/6): git-2.39.3-1.el8_8.ppc64le.rpm 1.2 MB/s | 104 kB 00:00
(2/6): perl-Error-0.17025-2.el8.noarch.rpm 992 kB/s | 46 kB 00:00
(3/6): git-core-doc-2.39.3-1.el8_8.noarch.rpm 16 MB/s | 3.0 MB 00:00
(4/6): perl-Git-2.39.3-1.el8_8.noarch.rpm 1.4 MB/s | 79 kB 00:00
(5/6): perl-TermReadKey-2.37-7.el8.ppc64le.rpm 949 kB/s | 42 kB 00:00
(6/6): git-core-2.39.3-1.el8_8.ppc64le.rpm 34 MB/s | 12 MB 00:00
----------------------------------------------------------------------------------------------------------------------
Total 43 MB/s | 15 MB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : git-core-2.39.3-1.el8_8.ppc64le 1/6
Installing : git-core-doc-2.39.3-1.el8_8.noarch 2/6
Installing : perl-TermReadKey-2.37-7.el8.ppc64le 3/6
Installing : perl-Error-1:0.17025-2.el8.noarch 4/6
Installing : perl-Git-2.39.3-1.el8_8.noarch 5/6
Installing : git-2.39.3-1.el8_8.ppc64le 6/6
Running scriptlet: git-2.39.3-1.el8_8.ppc64le 6/6
Verifying : git-2.39.3-1.el8_8.ppc64le 1/6
Verifying : git-core-2.39.3-1.el8_8.ppc64le 2/6
Verifying : git-core-doc-2.39.3-1.el8_8.noarch 3/6
Verifying : perl-Error-1:0.17025-2.el8.noarch 4/6
Verifying : perl-Git-2.39.3-1.el8_8.noarch 5/6
Verifying : perl-TermReadKey-2.37-7.el8.ppc64le 6/6
Installed products updated.
Installed:
git-2.39.3-1.el8_8.ppc64le git-core-2.39.3-1.el8_8.ppc64le git-core-doc-2.39.3-1.el8_8.noarch
perl-Error-1:0.17025-2.el8.noarch perl-Git-2.39.3-1.el8_8.noarch perl-TermReadKey-2.37-7.el8.ppc64le
Complete!
- Install/update dotnet
sudo dnf install dotnet-sdk-7.0
Updating Subscription Management repositories.
Red Hat Enterprise Linux 8 for Power, little endian - Supplementary (RPMs) 89 kB/s | 3.8 kB 00:00
Red Hat Enterprise Linux 8 for Power, little endian - AppStream (RPMs) 57 kB/s | 2.9 kB 00:00
Red Hat Enterprise Linux 8 for Power, little endian - BaseOS (RPMs) 88 kB/s | 4.1 kB 00:00
Dependencies resolved.
======================================================================================================================
Package Architecture Version Repository Size
======================================================================================================================
Installing:
dotnet ppc64le 7.0.105-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 18 k
Installing dependencies:
aspnetcore-runtime-7.0 ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 2.8 M
aspnetcore-targeting-pack-7.0 ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 1.6 M
dotnet-apphost-pack-7.0 ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 100 k
dotnet-host ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 199 k
dotnet-hostfxr-7.0 ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 174 k
dotnet-runtime-7.0 ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 7.8 M
dotnet-sdk-7.0 ppc64le 7.0.105-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 52 M
dotnet-targeting-pack-7.0 ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 2.9 M
dotnet-templates-7.0 ppc64le 7.0.105-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 3.9 M
netstandard-targeting-pack-2.1 ppc64le 7.0.105-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 1.5 M
Transaction Summary
======================================================================================================================
Install 11 Packages
Total download size: 73 M
Installed size: 308 M
Is this ok [y/N]: y
Downloading Packages:
(1/11): dotnet-7.0.105-2.el8_8.ppc64le.rpm 220 kB/s | 18 kB 00:00
(2/11): aspnetcore-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le.rpm 15 MB/s | 1.6 MB 00:00
(3/11): dotnet-apphost-pack-7.0-7.0.5-2.el8_8.ppc64le.rpm 1.8 MB/s | 100 kB 00:00
(4/11): aspnetcore-runtime-7.0-7.0.5-2.el8_8.ppc64le.rpm 17 MB/s | 2.8 MB 00:00
(5/11): dotnet-host-7.0.5-2.el8_8.ppc64le.rpm 3.3 MB/s | 199 kB 00:00
(6/11): dotnet-hostfxr-7.0-7.0.5-2.el8_8.ppc64le.rpm 2.3 MB/s | 174 kB 00:00
(7/11): dotnet-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le.rpm 14 MB/s | 2.9 MB 00:00
(8/11): dotnet-runtime-7.0-7.0.5-2.el8_8.ppc64le.rpm 16 MB/s | 7.8 MB 00:00
(9/11): dotnet-templates-7.0-7.0.105-2.el8_8.ppc64le.rpm 13 MB/s | 3.9 MB 00:00
(10/11): netstandard-targeting-pack-2.1-7.0.105-2.el8_8.ppc64le.rpm 11 MB/s | 1.5 MB 00:00
(11/11): dotnet-sdk-7.0-7.0.105-2.el8_8.ppc64le.rpm 29 MB/s | 52 MB 00:01
----------------------------------------------------------------------------------------------------------------------
Total 38 MB/s | 73 MB 00:01
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : dotnet-host-7.0.5-2.el8_8.ppc64le 1/11
Installing : aspnetcore-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le 2/11
Installing : dotnet-apphost-pack-7.0-7.0.5-2.el8_8.ppc64le 3/11
Installing : dotnet-hostfxr-7.0-7.0.5-2.el8_8.ppc64le 4/11
Installing : dotnet-runtime-7.0-7.0.5-2.el8_8.ppc64le 5/11
Installing : aspnetcore-runtime-7.0-7.0.5-2.el8_8.ppc64le 6/11
Installing : dotnet-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le 7/11
Installing : dotnet-templates-7.0-7.0.105-2.el8_8.ppc64le 8/11
Installing : netstandard-targeting-pack-2.1-7.0.105-2.el8_8.ppc64le 9/11
Installing : dotnet-sdk-7.0-7.0.105-2.el8_8.ppc64le 10/11
Installing : dotnet-7.0.105-2.el8_8.ppc64le 11/11
Running scriptlet: dotnet-7.0.105-2.el8_8.ppc64le 11/11
Verifying : aspnetcore-runtime-7.0-7.0.5-2.el8_8.ppc64le 1/11
Verifying : aspnetcore-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le 2/11
Verifying : dotnet-7.0.105-2.el8_8.ppc64le 3/11
Verifying : dotnet-apphost-pack-7.0-7.0.5-2.el8_8.ppc64le 4/11
Verifying : dotnet-host-7.0.5-2.el8_8.ppc64le 5/11
Verifying : dotnet-hostfxr-7.0-7.0.5-2.el8_8.ppc64le 6/11
Verifying : dotnet-runtime-7.0-7.0.5-2.el8_8.ppc64le 7/11
Verifying : dotnet-sdk-7.0-7.0.105-2.el8_8.ppc64le 8/11
Verifying : dotnet-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le 9/11
Verifying : dotnet-templates-7.0-7.0.105-2.el8_8.ppc64le 10/11
Verifying : netstandard-targeting-pack-2.1-7.0.105-2.el8_8.ppc64le 11/11
Installed products updated.
Installed:
aspnetcore-runtime-7.0-7.0.5-2.el8_8.ppc64le aspnetcore-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le
dotnet-7.0.105-2.el8_8.ppc64le dotnet-apphost-pack-7.0-7.0.5-2.el8_8.ppc64le
dotnet-host-7.0.5-2.el8_8.ppc64le dotnet-hostfxr-7.0-7.0.5-2.el8_8.ppc64le
dotnet-runtime-7.0-7.0.5-2.el8_8.ppc64le dotnet-sdk-7.0-7.0.105-2.el8_8.ppc64le
dotnet-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le dotnet-templates-7.0-7.0.105-2.el8_8.ppc64le
netstandard-targeting-pack-2.1-7.0.105-2.el8_8.ppc64le
Complete!
- Install/update the Shift tool
dotnet tool update -g dotnet-shift --version 1 --add-source https://www.myget.org/F/tmds/api/v3/index.json
You can invoke the tool using the following command: dotnet-shift
Tool 'dotnet-shift' (version '1.0.0') was successfully installed.
- Add dotnet tools to PATH
export PATH="$PATH:/home/cecuser/.dotnet/tools"
- Review the Shift usage and help information.
dotnet shift --help
Description:
A .NET tool for working with OpenShift
Usage:
dotnet-shift [command] [options]
Options:
-?, -h, --help Show help and usage information
--version Show version information
Commands:
login Log in to a server
deploy <PROJECT> Deploy a .NET application to OpenShift [default: .]
list List deployments
delete <APP> Delete an application
context Operate on connection contexts
- Create or clone a .NET project.
git clone https://github.com/paulchapmanibm/stayingalive.git
Cloning into 'stayingalive'...
remote: Enumerating objects: 136, done.
remote: Counting objects: 100% (136/136), done.
remote: Compressing objects: 100% (88/88), done.
remote: Total 136 (delta 54), reused 114 (delta 42), pack-reused 0
Receiving objects: 100% (136/136), 865.36 KiB | 15.18 MiB/s, done.
Resolving deltas: 100% (54/54), done.
- To log into the OpenShift cluster, copy the
oc login
command from the OpenShift Web Console and replaceoc
bydotnet shift. See Section 2.4 Copy login command for CLI use
if necessary. Your token will be different to below.
Note, say yes to insecure connections.

dotnet shift login --token=<your_token> --server=<your_server_url>
The connection is not trusted: The remote certificate is invalid because of errors in the certificate chain:
UntrustedRoot.
You can bypass the certificate check, but any data you send to the server could be intercepted by others.
Use insecure connections? [y/n] (n): y
Logged into 'https://api.p1382.cecc.ihost.com:6443' as 'cecuser' using the provided token.
What namespace would you like to use? default
How would you like to name this context? (default/api-p1382-cecc-ihost-com:6443/cecuser): default/api-p1382-cecc-ihost-com:6443/cecuser
The login context 'default/api-p1382-cecc-ihost-com:6443/cecuser' was updated.
Using namespace 'default' on server 'api.p1382.cecc.ihost.com'.
Deploy the application using Shift
- Change to the project directory.
cd /home/cecuser/build/stayingalive/stayingalive
- Deploy the .NET application with a single command!
dotnet shift deploy --expose
Deploying 'stayingalive' to namespace 'default' at 'https://api.p1382.cecc.ihost.com:6443'.
Retrieving existing resources...
Updating resources...
Uploading sources from directory '/home/cecuser/build/stayingalive'...
The build is running:
Receiving source from STDIN as archive ...
time="2023-06-08T10:46:48Z" level=info msg="Not using native diff for overlay, this may cause degraded performance for
building images: kernel has CONFIG_OVERLAY_FS_REDIRECT_DIR enabled"
I0608 10:46:48.353951 1 defaults.go:102] Defaulting to storage driver "overlay" with options
[mountopt=metacopy=on].
Caching blobs under "/var/cache/blobs".
Trying to pull
image-registry.openshift-image-registry.svc:5000/default/dotnet@sha256:123a4c2b812ab5b63017022e1c7a77051e8ccef7e7a96af
f5f2e27f9034049c7...
Getting image source signatures
Copying blob sha256:5a9dd0ea9aa0c53ebdfe8b13b96e6a8dc23df3c41161b4a2d5d75d42bfbf20fb
Copying blob sha256:cdc1eeb2ff7c0d91b77fc7380905c609f5e592eabc334cd45216394ae60a5759
Copying blob sha256:b7b266c137a567c08c67af32f48be66dca2e37779310a4f0f11254fb200547a1
Copying config sha256:2fcc920557a621073fdfce570202f901eb120832bc331e60a639417c65ed1b4e
Writing manifest to image destination
Storing signatures
Generating dockerfile with builder image
image-registry.openshift-image-registry.svc:5000/default/dotnet@sha256:123a4c2b812ab5b63017022e1c7a77051e8ccef7e7a96af
f5f2e27f9034049c7
Adding transient rw bind mount for /run/secrets/rhsm
STEP 1/9: FROM
image-registry.openshift-image-registry.svc:5000/default/dotnet@sha256:123a4c2b812ab5b63017022e1c7a77051e8ccef7e7a96af
f5f2e27f9034049c7
STEP 2/9: LABEL
"io.openshift.build.image"="image-registry.openshift-image-registry.svc:5000/default/dotnet@sha256:123a4c2b812ab5b6301
7022e1c7a77051e8ccef7e7a96aff5f2e27f9034049c7" "io.openshift.build.source-location"="/tmp/build/inputs"
STEP 3/9: ENV <<MASKED>>
STEP 4/9: USER root
STEP 5/9: COPY upload/src /tmp/src
STEP 6/9: RUN chown -R 1001:0 /tmp/src
STEP 7/9: USER 1001
STEP 8/9: RUN /usr/libexec/s2i/assemble
---> Installing application source...
Using SDK: 7.0.105
---> Restoring application dependencies...
Determining projects to restore...
Restored /opt/app-root/src/stayingalive/stayingalive.csproj (in 2.03 sec).
---> Publishing application...
MSBuild version 17.4.3+7e646be43 for .NET
stayingalive -> /opt/app-root/src/stayingalive/bin/Release/net7.0/stayingalive.dll
stayingalive -> /opt/app-root/app/
STEP 9/9: CMD /usr/libexec/s2i/run
COMMIT temp.builder.openshift.io/default/stayingalive-binary-1:fad46cbc
time="2023-06-08T10:47:35Z" level=warning msg="Adding metacopy option, configured globally"
Getting image source signatures
Copying blob sha256:5bfc4c1df46878869c2bc45286a02af61b5fec97e6170c1d76e00c3aa80f1518
Copying blob sha256:b0bef5d376466d102731266fe5c6f0cac3ac69b72b821f7dbd51b30d44825cef
Copying blob sha256:3cb02a08cd6f7d1b9afca0c90e5afa6be2a70df77389cd1435e8148ebad4ee52
Copying blob sha256:c330f42c61b5973d3537f5d63f3753af1d851ee28f86573e9a6e4910c09cdb58
Copying config sha256:6da4149c4c3472c6f8b9be280e8435a494a2a857907df257bcbb87352e36c0ef
Writing manifest to image destination
Storing signatures
--> 6da4149c4c3
Successfully tagged temp.builder.openshift.io/default/stayingalive-binary-1:fad46cbc
6da4149c4c3472c6f8b9be280e8435a494a2a857907df257bcbb87352e36c0ef
Pushing image image-registry.openshift-image-registry.svc:5000/default/stayingalive:latest ...
Getting image source signatures
Copying blob sha256:c330f42c61b5973d3537f5d63f3753af1d851ee28f86573e9a6e4910c09cdb58
Copying blob sha256:5a9dd0ea9aa0c53ebdfe8b13b96e6a8dc23df3c41161b4a2d5d75d42bfbf20fb
Copying blob sha256:b7b266c137a567c08c67af32f48be66dca2e37779310a4f0f11254fb200547a1
Copying blob sha256:cdc1eeb2ff7c0d91b77fc7380905c609f5e592eabc334cd45216394ae60a5759
Copying config sha256:6da4149c4c3472c6f8b9be280e8435a494a2a857907df257bcbb87352e36c0ef
Writing manifest to image destination
Storing signatures
Successfully pushed
image-registry.openshift-image-registry.svc:5000/default/stayingalive@sha256:6e0a65a47c775e14ad156c64ad20f65c403d71148
8d3241af59404c32f37994a
Push successful
The image is being deployed.
The deployment finished successfully. There is 1 available pod.
The application is exposed at 'http://stayingalive-default.apps.p1382.cecc.ihost.com'.
Verify the application & play the game
- Verify the Application is Running. To view your new application, paste the URL from the last line of output from earlier “dotnet shift deploy” command into the address bar of your web browser and hit enter.
Push successful
The image is being deployed.
The deployment finished successfully. There is 1 available pod.
The application is exposed at 'http://stayingalive-default.apps.p1382.cecc.ihost.com'
- Left click on the Accelerate button to gain height and navigate through obstacles for as long as you can.

Try out other Shift features
- Try dotnet shift to list applications
dotnet shift list
APP DEPLOYMENT BUILD SERVICE ROUTE POD
stayingalive stayingalive (1/1) stayingalive-binary stayingalive stayingalive stayingalive-54548d599-fckw7 (R)
- Try dotnet shift to delete applications
dotnet shift delete stayingalive
Deleting ImageStream 'stayingalive'
Deleting ConfigMap 'stayingalive'
Deleting Route 'stayingalive'
Deleting Service 'stayingalive'
Deleting Deployment 'stayingalive'
Deleting BuildConfig 'stayingalive-binary'
11 Deploy .NET game with build-image
This part of the demo will guide you through process of creating a new project and building the .Net based game using the dotnet build-image
This part of the demo will be completed using the cecuser user.
You can watch a recording of this exercise
Install/provide prerequisites
Follow the below steps to add the .Net 7 builder image to OCP.
- Log in to the OCP Bastion Server as the cecuser. Check you have the correct user. The whoami command should return cecuser.
whoami
cecuser
- Change to the build directory.
cd /home/cecuser/build
- Install/update Git.
sudo dnf install git
Updating Subscription Management repositories.
Red Hat Enterprise Linux 8 for Power, little endian - Supplementary (RPMs) 83 kB/s | 3.8 kB 00:00
Red Hat Enterprise Linux 8 for Power, little endian - AppStream (RPMs) 69 kB/s | 2.9 kB 00:00
Red Hat Enterprise Linux 8 for Power, little endian - BaseOS (RPMs) 105 kB/s | 4.1 kB 00:00
Dependencies resolved.
======================================================================================================================
Package Architecture Version Repository Size
======================================================================================================================
Installing:
git ppc64le 2.39.3-1.el8_8 rhel-8-for-ppc64le-appstream-rpms 104 k
Installing dependencies:
git-core ppc64le 2.39.3-1.el8_8 rhel-8-for-ppc64le-appstream-rpms 12 M
git-core-doc noarch 2.39.3-1.el8_8 rhel-8-for-ppc64le-appstream-rpms 3.0 M
perl-Error noarch 1:0.17025-2.el8 rhel-8-for-ppc64le-appstream-rpms 46 k
perl-Git noarch 2.39.3-1.el8_8 rhel-8-for-ppc64le-appstream-rpms 79 k
perl-TermReadKey ppc64le 2.37-7.el8 rhel-8-for-ppc64le-appstream-rpms 42 k
Transaction Summary
======================================================================================================================
Install 6 Packages
Total download size: 15 M
Installed size: 53 M
Is this ok [y/N]: y
Downloading Packages:
(1/6): git-2.39.3-1.el8_8.ppc64le.rpm 1.2 MB/s | 104 kB 00:00
(2/6): perl-Error-0.17025-2.el8.noarch.rpm 992 kB/s | 46 kB 00:00
(3/6): git-core-doc-2.39.3-1.el8_8.noarch.rpm 16 MB/s | 3.0 MB 00:00
(4/6): perl-Git-2.39.3-1.el8_8.noarch.rpm 1.4 MB/s | 79 kB 00:00
(5/6): perl-TermReadKey-2.37-7.el8.ppc64le.rpm 949 kB/s | 42 kB 00:00
(6/6): git-core-2.39.3-1.el8_8.ppc64le.rpm 34 MB/s | 12 MB 00:00
----------------------------------------------------------------------------------------------------------------------
Total 43 MB/s | 15 MB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : git-core-2.39.3-1.el8_8.ppc64le 1/6
Installing : git-core-doc-2.39.3-1.el8_8.noarch 2/6
Installing : perl-TermReadKey-2.37-7.el8.ppc64le 3/6
Installing : perl-Error-1:0.17025-2.el8.noarch 4/6
Installing : perl-Git-2.39.3-1.el8_8.noarch 5/6
Installing : git-2.39.3-1.el8_8.ppc64le 6/6
Running scriptlet: git-2.39.3-1.el8_8.ppc64le 6/6
Verifying : git-2.39.3-1.el8_8.ppc64le 1/6
Verifying : git-core-2.39.3-1.el8_8.ppc64le 2/6
Verifying : git-core-doc-2.39.3-1.el8_8.noarch 3/6
Verifying : perl-Error-1:0.17025-2.el8.noarch 4/6
Verifying : perl-Git-2.39.3-1.el8_8.noarch 5/6
Verifying : perl-TermReadKey-2.37-7.el8.ppc64le 6/6
Installed products updated.
Installed:
git-2.39.3-1.el8_8.ppc64le git-core-2.39.3-1.el8_8.ppc64le git-core-doc-2.39.3-1.el8_8.noarch
perl-Error-1:0.17025-2.el8.noarch perl-Git-2.39.3-1.el8_8.noarch perl-TermReadKey-2.37-7.el8.ppc64le
Complete!
- Install/update dotnet.
sudo dnf install dotnet-sdk-7.0
Updating Subscription Management repositories.
Red Hat Enterprise Linux 8 for Power, little endian - Supplementary (RPMs) 89 kB/s | 3.8 kB 00:00
Red Hat Enterprise Linux 8 for Power, little endian - AppStream (RPMs) 57 kB/s | 2.9 kB 00:00
Red Hat Enterprise Linux 8 for Power, little endian - BaseOS (RPMs) 88 kB/s | 4.1 kB 00:00
Dependencies resolved.
======================================================================================================================
Package Architecture Version Repository Size
======================================================================================================================
Installing:
dotnet ppc64le 7.0.105-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 18 k
Installing dependencies:
aspnetcore-runtime-7.0 ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 2.8 M
aspnetcore-targeting-pack-7.0 ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 1.6 M
dotnet-apphost-pack-7.0 ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 100 k
dotnet-host ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 199 k
dotnet-hostfxr-7.0 ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 174 k
dotnet-runtime-7.0 ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 7.8 M
dotnet-sdk-7.0 ppc64le 7.0.105-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 52 M
dotnet-targeting-pack-7.0 ppc64le 7.0.5-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 2.9 M
dotnet-templates-7.0 ppc64le 7.0.105-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 3.9 M
netstandard-targeting-pack-2.1 ppc64le 7.0.105-2.el8_8 rhel-8-for-ppc64le-appstream-rpms 1.5 M
Transaction Summary
======================================================================================================================
Install 11 Packages
Total download size: 73 M
Installed size: 308 M
Is this ok [y/N]: y
Downloading Packages:
(1/11): dotnet-7.0.105-2.el8_8.ppc64le.rpm 220 kB/s | 18 kB 00:00
(2/11): aspnetcore-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le.rpm 15 MB/s | 1.6 MB 00:00
(3/11): dotnet-apphost-pack-7.0-7.0.5-2.el8_8.ppc64le.rpm 1.8 MB/s | 100 kB 00:00
(4/11): aspnetcore-runtime-7.0-7.0.5-2.el8_8.ppc64le.rpm 17 MB/s | 2.8 MB 00:00
(5/11): dotnet-host-7.0.5-2.el8_8.ppc64le.rpm 3.3 MB/s | 199 kB 00:00
(6/11): dotnet-hostfxr-7.0-7.0.5-2.el8_8.ppc64le.rpm 2.3 MB/s | 174 kB 00:00
(7/11): dotnet-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le.rpm 14 MB/s | 2.9 MB 00:00
(8/11): dotnet-runtime-7.0-7.0.5-2.el8_8.ppc64le.rpm 16 MB/s | 7.8 MB 00:00
(9/11): dotnet-templates-7.0-7.0.105-2.el8_8.ppc64le.rpm 13 MB/s | 3.9 MB 00:00
(10/11): netstandard-targeting-pack-2.1-7.0.105-2.el8_8.ppc64le.rpm 11 MB/s | 1.5 MB 00:00
(11/11): dotnet-sdk-7.0-7.0.105-2.el8_8.ppc64le.rpm 29 MB/s | 52 MB 00:01
----------------------------------------------------------------------------------------------------------------------
Total 38 MB/s | 73 MB 00:01
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : dotnet-host-7.0.5-2.el8_8.ppc64le 1/11
Installing : aspnetcore-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le 2/11
Installing : dotnet-apphost-pack-7.0-7.0.5-2.el8_8.ppc64le 3/11
Installing : dotnet-hostfxr-7.0-7.0.5-2.el8_8.ppc64le 4/11
Installing : dotnet-runtime-7.0-7.0.5-2.el8_8.ppc64le 5/11
Installing : aspnetcore-runtime-7.0-7.0.5-2.el8_8.ppc64le 6/11
Installing : dotnet-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le 7/11
Installing : dotnet-templates-7.0-7.0.105-2.el8_8.ppc64le 8/11
Installing : netstandard-targeting-pack-2.1-7.0.105-2.el8_8.ppc64le 9/11
Installing : dotnet-sdk-7.0-7.0.105-2.el8_8.ppc64le 10/11
Installing : dotnet-7.0.105-2.el8_8.ppc64le 11/11
Running scriptlet: dotnet-7.0.105-2.el8_8.ppc64le 11/11
Verifying : aspnetcore-runtime-7.0-7.0.5-2.el8_8.ppc64le 1/11
Verifying : aspnetcore-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le 2/11
Verifying : dotnet-7.0.105-2.el8_8.ppc64le 3/11
Verifying : dotnet-apphost-pack-7.0-7.0.5-2.el8_8.ppc64le 4/11
Verifying : dotnet-host-7.0.5-2.el8_8.ppc64le 5/11
Verifying : dotnet-hostfxr-7.0-7.0.5-2.el8_8.ppc64le 6/11
Verifying : dotnet-runtime-7.0-7.0.5-2.el8_8.ppc64le 7/11
Verifying : dotnet-sdk-7.0-7.0.105-2.el8_8.ppc64le 8/11
Verifying : dotnet-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le 9/11
Verifying : dotnet-templates-7.0-7.0.105-2.el8_8.ppc64le 10/11
Verifying : netstandard-targeting-pack-2.1-7.0.105-2.el8_8.ppc64le 11/11
Installed products updated.
Installed:
aspnetcore-runtime-7.0-7.0.5-2.el8_8.ppc64le aspnetcore-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le
dotnet-7.0.105-2.el8_8.ppc64le dotnet-apphost-pack-7.0-7.0.5-2.el8_8.ppc64le
dotnet-host-7.0.5-2.el8_8.ppc64le dotnet-hostfxr-7.0-7.0.5-2.el8_8.ppc64le
dotnet-runtime-7.0-7.0.5-2.el8_8.ppc64le dotnet-sdk-7.0-7.0.105-2.el8_8.ppc64le
dotnet-targeting-pack-7.0-7.0.5-2.el8_8.ppc64le dotnet-templates-7.0-7.0.105-2.el8_8.ppc64le
netstandard-targeting-pack-2.1-7.0.105-2.el8_8.ppc64le
Complete!
- Install/update the dotnet build-image tool.
dotnet tool install -g dotnet-build-image
You can invoke the tool using the following command: dotnet-build-image
Tool 'dotnet-build-image' (version '0.5.2') was successfully installed.
- Add dotnet tools to PATH
export PATH="$PATH:/home/cecuser/.dotnet/tools"
- Review the tool help information.
dotnet build-image --help
Description:
Build a container image from a .NET project.
Usage:
build-image [<PROJECT>] [options]
Arguments:
<PROJECT> .NET project to build [default: .]
Options:
-b, --base <base> Flavor of the base image
-t, --tag <tag> Name for the built image
-a, --arch <arch> Target architecture ('x64'/'arm64'/'s390x'/'ppc64le')
The base image needs to support the selected architecture
--push After the build, push the image to the repository
--portable Avoid using features that make the Containerfile not
portable
--context <context> Context directory for the build [default: .]
--as-file <as-file> Generates a Containerfile with the specified name
--print Print the Containerfile
--version Show version information
-?, -h, --help Show help and usage information
- Create or clone a .NET project.
git clone https://github.com/paulchapmanibm/stayingalive.git
Cloning into 'stayingalive'...
remote: Enumerating objects: 136, done.
remote: Counting objects: 100% (136/136), done.
remote: Compressing objects: 100% (88/88), done.
remote: Total 136 (delta 54), reused 114 (delta 42), pack-reused 0
Receiving objects: 100% (136/136), 865.36 KiB | 15.18 MiB/s, done.
Resolving deltas: 100% (54/54), done.
- Remove any existing Dockerfiles
cd stayingalive
ls
Dockerfile Dockerfile.ppc64le Dockerfile.x86 README.md stayingalive stayingalive.sln
rm Dockerfil*
ls
README.md stayingalive stayingalive.sln
- Move to the directory containing the project file *.csproj
cd stayingalive
ls
appsettings.Development.json Pages Properties stayingalive.csproj.ppc64le wwwroot
appsettings.json Program.cs stayingalive.csproj stayingalive.csproj.x86
Build and run the application using build-image
- We now have a .NET source project without a Dockerfile, which is required to build a container. We will now build a container from the .NET project and the Dockerfile will be automatically created by the build-image tool.
dotnet build-image -t game:latest --arch ppc64le --base ubi
Building image 'game:latest' from project '/home/cecuser/build/stayingalive/stayingalive/stayingalive.csproj'.
[1/2] STEP 1/13: FROM registry.access.redhat.com/ubi8/dotnet-70:latest AS build-env
time="2023-06-09T05:50:45-04:00" level=warning msg="missing \"UID\" build argument. Try adding \"--build-arg UID=<VALUE>\" to the command line"
time="2023-06-09T05:50:45-04:00" level=warning msg="missing \"GID\" build argument. Try adding \"--build-arg GID=<VALUE>\" to the command line"
time="2023-06-09T05:50:45-04:00" level=warning msg="missing \"UID\" build argument. Try adding \"--build-arg UID=<VALUE>\" to the command line"
time="2023-06-09T05:50:45-04:00" level=warning msg="missing \"GID\" build argument. Try adding \"--build-arg GID=<VALUE>\" to the command line"
Trying to pull registry.access.redhat.com/ubi8/dotnet-70:latest...
Getting image source signatures
Checking if image destination supports signatures
Copying blob sha256:b7b266c137a567c08c67af32f48be66dca2e37779310a4f0f11254fb200547a1
Copying blob sha256:5a9dd0ea9aa0c53ebdfe8b13b96e6a8dc23df3c41161b4a2d5d75d42bfbf20fb
Copying blob sha256:cdc1eeb2ff7c0d91b77fc7380905c609f5e592eabc334cd45216394ae60a5759
Copying config sha256:2fcc920557a621073fdfce570202f901eb120832bc331e60a639417c65ed1b4e
Writing manifest to image destination
Storing signatures
[1/2] STEP 2/13: ARG UID
--> e12b1a78092
[1/2] STEP 3/13: ARG GID
--> 8a73d9f1f2f
[1/2] STEP 4/13: USER 0
--> f1906ee1d0a
[1/2] STEP 5/13: COPY --from=registry.access.redhat.com/ubi8/dotnet-70-runtime:latest /etc/passwd /etc/group /scratch/etc
Trying to pull registry.access.redhat.com/ubi8/dotnet-70-runtime:latest...
Getting image source signatures
Checking if image destination supports signatures
Copying blob sha256:cdc1eeb2ff7c0d91b77fc7380905c609f5e592eabc334cd45216394ae60a5759
Copying blob sha256:5a9dd0ea9aa0c53ebdfe8b13b96e6a8dc23df3c41161b4a2d5d75d42bfbf20fb
Copying config sha256:dc6c5afa3a2cc506822888e8898444ba6b5402e7d7503afe041bf5f3c74b9ddc
Writing manifest to image destination
Storing signatures
--> ae3bd9007cd
[1/2] STEP 6/13: RUN grep ":$GID:" /scratch/etc/group || echo "app:x:$GID:" >>/scratch/etc/group && mkdir -p /rootfs/etc && cp /scratch/etc/group /rootfs/etc && grep ":x:$UID:" /scratch/etc/passwd || echo "app:x:$UID:$GID::/home/app:/usr/sbin/nologin" >>/scratch/etc/passwd && mkdir -p /rootfs/etc && cp /scratch/etc/passwd /rootfs/etc
root:x:0:
default:x:1001:0:Default Application User:/opt/app-root:/sbin/nologin
--> aa2950d1e8c
[1/2] STEP 7/13: RUN mkdir -p /rootfs/home/app
--> 84ce742a52e
[1/2] STEP 8/13: ENV HOME=/home/build
--> c02495b765f
[1/2] STEP 9/13: WORKDIR /src
--> 48346f76b12
[1/2] STEP 10/13: COPY . ./
--> 02a024a860a
[1/2] STEP 11/13: RUN --mount=type=cache,id=nuget,target=/home/build/.nuget/packages,Z dotnet restore .
Determining projects to restore...
Restored /src/stayingalive.csproj (in 494 ms).
--> 5375a8314d9
[1/2] STEP 12/13: RUN --mount=type=cache,id=nuget,target=/home/build/.nuget/packages,Z dotnet publish --no-restore -c Release -o /rootfs/app .
MSBuild version 17.4.3+7e646be43 for .NET
stayingalive -> /src/bin/Release/net7.0/stayingalive.dll
stayingalive -> /rootfs/app/
time="2023-06-09T05:51:33-04:00" level=warning msg="archive: skipping \"/home/cecuser/.local/share/containers/storage/overlay/2724961b3c9ac0ddff71db351299bdaafcb3bbab498647ee9ef44b4faba56099/diff/tmp/dotnet-diagnostic-36-4413582-socket\" since it is a socket"
time="2023-06-09T05:51:33-04:00" level=warning msg="archive: skipping \"/home/cecuser/.local/share/containers/storage/overlay/2724961b3c9ac0ddff71db351299bdaafcb3bbab498647ee9ef44b4faba56099/diff/tmp/zzi6tW1mhG_JriOOInfq8ZYXj96AzWfNu_SpKAdhwrc\" since it is a socket"
--> 3e1468996b2
[1/2] STEP 13/13: RUN chgrp -R $GID /rootfs/app /rootfs/home/app && chmod -R g=u /rootfs/app /rootfs/home/app && chown -R $UID:$GID /rootfs/app /rootfs/home/app
--> b19f9dce269
[2/2] STEP 1/8: FROM registry.access.redhat.com/ubi8/dotnet-70-runtime:latest
[2/2] STEP 2/8: ARG UID
--> 1df1ba65315
[2/2] STEP 3/8: ARG GID
--> 9a3dcbeac18
[2/2] STEP 4/8: COPY --from=build-env /rootfs /
--> 4959b146e17
[2/2] STEP 5/8: USER $UID:$GID
--> 4dc2e2e5c30
[2/2] STEP 6/8: ENV ASPNETCORE_URLS=http://*:8080 HOME=/home/app
--> 775637f875c
[2/2] STEP 7/8: WORKDIR /app
--> 9ddac22e413
[2/2] STEP 8/8: ENTRYPOINT ["dotnet", "/app/stayingalive.dll"]
[2/2] COMMIT game:latest
--> b74188c029d
Successfully tagged localhost/game:latest
b74188c029dfb0c6449be4c7a4ca7f67cc33d045547202d8a3414b4fcbc3c791
- We can see that the build-image tool has built the container from source, automatically creating it’s own Dockerfile, from a Universal Base Image obtained from the Red Hat registry.
podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/game latest b74188c029df 2 minutes ago 261 MB
<none> <none> b19f9dce2695 2 minutes ago 662 MB
registry.access.redhat.com/ubi8/dotnet-70 latest 2fcc920557a6 4 weeks ago 627 MB
registry.access.redhat.com/ubi8/dotnet-70-runtime latest dc6c5afa3a2c 4 weeks ago 253 MB
- Now start the container, specifying the network ports to be used.
podman run -p 8080:8080 game
warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
Storing keys in a directory '/home/app/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
No XML encryptor configured. Key {2c358c35-8bdf-4181-af85-1cc3024cd7f3} may be persisted to storage in unencrypted form.
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://[::]:8080
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
Content root path: /app
Verify and play the game
- Verify the Application is Running. To view your new application, browse to the previously specified network ports and IP address of your bastion server.
http://<your_IP_address:8080/
For example:
http://129.40.95.217:8080/

12 Optional Unguided Exercises
IBM Power Development
Review the PDEX .NET Blog of Blogs
Hello World
Cross build .NET 7 on x86 for IBM Power
This blog shows you how to take the upstream .NET code and build an SDK for ppc64le on the distro of your choice, which is a longer, more complex task.
Lift & shift your existing .NET 7 applications to Linux on Power
- Demystifying .NET NuGet package compatibility on IBM Power. In this blog, you’ll get a crash course on NuGet, the official package manager for .NET that empowers developers to seamlessly package and distribute their software crafted using .NET framework.
- This blog, IdentityServer (SQLite DB) on .NET 7, shows you how to migrate a .NET 3.1 application (IdentityServer) with a SQLite backend to .NET 7 on a Power system running Red Hat Enterprise Linux (RHEL) 8.7 or 9.1.
Connect your .NET application to a database.
A .NET application can connect to backend database servers using Entity Framework (EF) Core, ADO.NET, ODBC, or native drivers. The following blogs cover several of these scenarios based on whether the database is on the same server as the .NET app or not:
Connect to a backend database on the SAME system
- C# program that connects to MariaDB using an ODBC connector
- C# program that connects to a NoSQL database (MongoDB using native drivers)
- C# program that connects to Postgres using EF Core
- C# program that connects to SQLite database using EF Core
- C# program that connects to MySQL server using ADO.Net
- C# application that connects to Microsoft SQL database
- C# application that connects to EDB PostgreSQL
- C# application that connects to Apache Cassandra
Connect to a backend database on a DIFFERENT system.
- C# program on Linux partition connects to remote database server on IBM i using ODBC.
- C# program on Linux partition that connects to Oracle on an AIX partition.
- Advanced Use Cases
- Develop .NET applications on IBM Power using Virtual Studio Code with OpenShift Dev Spaces. In this blog, you’ll learn to install and use Red Hat OpenShift Dev Spaces to code, build, test, run, and debug your .NET applications on Power.
- Grpc.Tools package for C# on Power. In this blog, you’ll learn how to build the Grpc.Tools package for C# on IBM Linux on Power. We’ll walk you through the process of verifying the port of the Grpc.Tools package on Power, using a sample gRPC application written in C# giving you a better understanding of how to leverage this package to create efficient APIs.
Microsoft .NET Documentation
https://learn.microsoft.com/en-us/dotnet/
- Microsoft .NET Tutorials
https://learn.microsoft.com/en-us/dotnet/core/tutorials/
- Build your first web app with ASP.NET Core using Blazor
https://dotnet.microsoft.com/en-us/learn/aspnet/blazor-tutorial/intro
- Get started with ASP.NET Core SignalR
13. Summary and Next Steps
What You’ve Accomplished
Throughout this hands-on lab, you’ve successfully:
1. Set up and configured development environments for .NET on IBM Power, including:
– Installing .NET SDK 7.0 on RHEL
– Configuring OpenShift for .NET deployments
– Setting up necessary tools like Git and Podman
2. Created and deployed .NET applications using multiple approaches:
– Direct deployment on RHEL
– Manual containerization with Podman
– OpenShift S2I (Source-to-Image) deployment
– Using specialized tools like dotnet-shift and build-image
3. Worked with different application types:
– Console applications
– Web applications using ASP.NET Core
– Real-time communication apps using SignalR
– Interactive game applications
– Blazor web applications
4. Gained practical experience with:
– Source code management using GitHub
– Container registry operations with Quay.io
– OpenShift deployment workflows
– Container orchestration and management
Key Takeaways
1. Deployment Flexibility
– .NET applications can be deployed directly on RHEL or containerized
– Multiple deployment methods are available to suit different needs
– OpenShift provides enterprise-grade orchestration capabilities
2. Development Tools
– Rich ecosystem of tools available for Power platform
– Seamless integration with standard development workflows
– Various options for building and managing containers
3. Enterprise Readiness
– Production-grade deployment options
– Scalable container-based solutions
– Integration with enterprise systems and tools
Next Steps
To continue your journey with .NET on IBM Power, consider:
1. Advanced Development
– Explore more complex application architectures
– Implement microservices using .NET – This lab includes .NET microservices
– Integrate with databases and other backend services
2. Production Deployment
– Set up CI/CD pipelines
– Implement monitoring and logging
– Configure high availability and scaling
3. Additional Resources
– IBM Power Development Community
– Microsoft .NET Documentation
– Red Hat OpenShift Documentation
– Community forums and support channels
4. Optional Learning Paths
– Database connectivity
– Performance optimization
– Security hardening
– Advanced OpenShift features
Getting Help
Remember that you can always refer to:
– Official IBM Power documentation
– Microsoft .NET documentation
– Red Hat OpenShift documentation
– IBM Power Developer community forums
– Red Hat customer support
You’ve now completed the foundational steps for developing and deploying .NET applications on IBM Power systems. This knowledge provides a solid base for building and running enterprise .NET applications on the Power platform.
Leave a Reply