RUN ORACLE LINUX 8.X DOCKER CONTAINER ON WINDOWS 10 WITH WSL2

The purpose of this guide is to run an Oracle Linux container on a Windows 10 system using Windows Subsystem for Linux v2.
(This may be an alternative to using a full-blown hypervisor type 2 such as Oracle VirtualBox or VMWare Player/Workstation.)

NOTE: Using container images from the official Oracle repository
NOTE: You will need to be running Windows 10 build 18917 or higher to use WSL 2. If you are on an earlier Windows 10 build, launch Windows Update Settings, you should be able to update it to the latest available version.
NOTE: there are docker images for 7/8/9 and slim versions of 7/8/9 (minimal environment with minimal number of packages) from the ghcr.io repository.

1. Prepare an Oracle Linux 8.x container and export it to a single TAR file using an existing Linux system as the work platform:

[root@wip]# yum install -y docker
[root@wip]# usermod -aG docker root
[root@wip]# newgrp docker
[root@wip]# id
uid=0(root) gid=992(docker) groups=992(docker),0(root)
[root@wip]#
[root@wip]# systemctl start docker.service
[root@wip]# systemctl enable docker.service

– Create the Dockerfile to use to build the container:
[root@wip]# vi Dockerfile
[root@wip]# cat Dockerfile
FROM ghcr.io/oracle/oraclelinux:8

CMD [“/bin/bash”]

– Build the docker container:
[root@wip]# docker build -t ghcr.io/oracle/oraclelinux:8 .
Sending build context to Docker daemon 23.04kB
Step 1/2 : FROM ghcr.io/oracle/oraclelinux:8
8: Pulling from oracle/oraclelinux
4c770e098606: Pull complete
Digest: sha256:07a995ecaf9db1ce613648a08facc162de69f26c39712f1acc93629c2e6c4e73
Status: Downloaded newer image for ghcr.io/oracle/oraclelinux:8
—> b0045ea7bbde
Step 2/2 : CMD [“/bin/bash”]
—> Running in 168cb6d08c9e
Removing intermediate container 168cb6d08c9e
—> 53be01d92e18
Successfully built 53be01d92e18
Successfully tagged ghcr.io/oracle/oraclelinux:8

– Test the container:
[root@wip]# docker run -it 53be01d92e18
[root@ec6e4b0f7c3b /]# cat /etc/oracle-release
Oracle Linux Server release 8.7
[root@ec6e4b0f7c3b /]# exit

– List all containers (note the container id ec6e4b0f7c3b associated with the image id 53be01d92e18 from the earlier build command output):

[root@wip]# docker ps -a
CONTAINER ID    IMAGE          COMMAND       CREATED              STATUS                         PORTS     NAMES
ec6e4b0f7c3b    53be01d92e18   "/bin/bash"   About a minute ago   Exited (0) 23 seconds ago                reverent_ellis

– Export the container into a single TAR file (222M size):
[root@wip]# docker export –output=”oellinux8.tar” aa565b335857

– Optionally zip the file (85MB zipped) to reduce the amount of data transferred when copying it to the Windows 10 system:
[root@wip]# gzip oellinux8.tar

– Transfer the container output TAR file to the Windows 10 system. In this case I will be using pscp to pull the file down into the Windows 10 system using a user other than root, so I copied the file to /tmp which is accessible to all users and changed the permission on the file so other users can read it:
[root@wip]# cp oellinux8.tar.gz /tmp/
[root@wip]# chmod 666 /tmp/oellinux8.tar.gz

2. SETUP WSL2 on Windows 10:
– Using elavated/admin powershell, run: Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
– Using elavated/admin command or powershell, run: dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
– Reboot the Windows 10 system (WSL2 upgrade fails without a reboot after installing WSL)
– Upgrade WSL to WSL2 via the installer https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

3. Pull down the container file to the local Windows 10 system with WSL2 installed:
C:\Users\user1> md wsl2\oellinux8
C:\Users\user1\wsl2\oellinux8>cd wsl2\oellinux8
C:\Users\user1\wsl2\oellinux8>pscp -i ….\Downloads\centos8.ppk ec2-user@my-linux-wip-server:/tmp/oellinux8.tar.gz .

4. Unzip the container file oellinux8.tar.gz (if you compressed the original TAR file):

5. Import the TAR file into WSL (syntax: wsl –import [DISTRO NAME] [STORAGE LOCATION] [FILE NAME]):
C:\Users\user1\wsl2\oellinux8>wsl –import oellinux8 “C:\Users\user1\wsl2\oellinux8” oellinux8.tar

NOTE: the import step extracts the TAR file into rootfs and temp directories:
C:\Users\user1\wsl2\oellinux8>dir
12/07/2022 11:47 PM 232,101,888 oellinux8.tar
12/07/2022 11:59 PM 84,593,746 oellinux8.tar.gz
12/08/2022 12:25 AM rootfs
12/08/2022 12:46 AM temp

6. Start the new WSL container (which ends at the running Linux prompt):
C:\Users\user1\wsl2\oellinux8> wsl -d oellinux8
[root@mywinpc wsl2]#

7. Execute some commands in the running container:
[root@mywinpc wsl2]# ping google.com
PING google.com (172.217.7.110) 56(84) bytes of data.
64 bytes from slc08s01-in-f14.1e100.net (172.217.7.110): icmp_seq=1 ttl=59 time=4.64 ms
64 bytes from slc08s01-in-f14.1e100.net (172.217.7.110): icmp_seq=2 ttl=59 time=5.59 ms
^C
— google.com ping statistics —
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 4.639/5.116/5.594/0.482 ms
[root@mywinpc wsl2]#
[root@mywinpc wsl2]# yum repolist
repo id repo name
ol8_appstream Oracle Linux 8 Application Stream (x86_64)
ol8_baseos_latest Oracle Linux 8 BaseOS Latest (x86_64)
[root@mywinpc user1]#
[root@mywinpc user1]# yum provides gdisk
Oracle Linux 8 BaseOS Latest (x86_64) 805 kB/s | 53 MB 01:07
Oracle Linux 8 Application Stream (x86_64) 926 kB/s | 42 MB 00:45
Last metadata expiration check: 0:00:14 ago on Thu 08 Dec 2022 12:29:18 AM MST.
gdisk-1.0.3-6.el8.x86_64 : An fdisk-like partitioning tool for GPT disks
Repo : ol8_baseos_latest
Matched from:
Provide : gdisk = 1.0.3-6.el8

gdisk-1.0.3-9.el8.x86_64 : An fdisk-like partitioning tool for GPT disks
Repo : ol8_baseos_latest
Matched from:
Provide : gdisk = 1.0.3-9.el8

gdisk-1.0.3-11.el8.x86_64 : An fdisk-like partitioning tool for GPT disks
Repo : ol8_baseos_latest
Matched from:
Provide : gdisk = 1.0.3-11.el8

[root@mywinpc user1]#

8. Optionally ENTER exit command to quit the running Linux container:
[root@mywinpc user1]# exit
C:\Users\user1\wsl2\oellinux8>

—————— END OF PROCEDURE ———————————

The following setup is to allow remote connectivity to the container

- Start a  temporary container (e.g., using the image id) to copy SSHD config files from it:
[root@ip-172-31-6-136 ~]# mkdir /oel8_etc_ssh
[root@ip-172-31-6-136 ~]# docker run --name wip -it -v /oel8_etc_ssh:/tmp/mpoint 18a22840eed9
[root@609b0ec071bb /]#
[root@609b0ec071bb /]# cp -a /etc/ssh /tmp/mpoint/
[root@609b0ec071bb /]# exit

- Delete the temporary container:
[root@ip-172-31-6-136 ~]# docker rm wip

- Start the "production" container with /oel8_etc_ssh/ssh on the host mounted to /etc/ssh in the container (running headless or detached mode with "-d"):
  NOTE: mapped port 2222/tcp on the host to the SSH port in the container. This is handy to access the container remotely from outside the host.
[root@ip-172-31-6-136 ~]# docker run --name oel87c -it -p 2222:22 -v /oel8_etc_ssh/ssh:/etc/ssh -d 18a22840eed9

- Attach to the console of the container:
[root@ip-172-31-6-136 ~]# docker attach d99789174764

- Create the ssh host keys (one-time task since they are stored persistently on the underlying host):
[root@d99789174764 /]# ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ''
[root@d99789174764 /]# ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N ''
[root@d99789174764 /]# ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ''

- Create the system log file (otherwise SSHD will be unable to authenticate login attempts):
[root@d99789174764 /]# touch /var/log/messages

- Start SSHD service:
[root@d99789174764 /]# /usr/sbin/sshd &

- Add a user to the container to login remotely:
[root@d99789174764 /]# useradd user1
[root@d99789174764 /]# passwd user1

- Optionally install/configure visudo to allow "user1" switch to the root user:
[root@d99789174764 /]# yum install -y sudo
[root@d99789174764 /]# visudo
[root@d99789174764 /]# grep user1 /etc/sudoers
user1   ALL=(ALL)       NOPASSWD: ALL
[root@d99789174764 /]#

- Detach from the container and keep it running: Press Ctrl-P, followed by Ctrl-Q,
  NOTE: if you mistakenly typed exit in the container which causes it to stop, start it again with "docker start <container-id>" on the host

- It is now possible to access the container remotely from outside the host. SSH to the container using the hosts' IP address on port 2222/tcp e.g.
  From a Windows/Linux system (you can also use Putty): ssh user@<host-ip> -p 2222

------------------- END -------------------

- Sample command to retrieve the IP of the container from the underlying host. [root@ip-172-31-6-136 ~]# docker ps    (command to get the container id)
[root@ip-172-31-6-136 ~]# docker container inspect -f '{{ .NetworkSettings.IPAddress }}' d99789174764
172.17.0.2

- Note: mounting the whole /etc and /var/log to directories on the underlying host should help to "persist" all the relevant configuration of the container.

References:
https://learn.microsoft.com/en-us/windows/wsl/install-manual
https://www.sanner.io/posts/2022/03/create-a-custom-linux-setup-for-wsl2/
https://learn.microsoft.com/en-us/windows/wsl/use-custom-distro
https://www.sanner.io/posts/2022/03/create-a-custom-linux-setup-for-wsl2/
https://learn.microsoft.com/en-us/windows/wsl/install-manual
https://hub.docker.com/_/oraclelinux?tab=tags
https://github.com/oracle/container-images/pkgs/container/oraclelinux
https://yum.oracle.com/oracle-linux-isos.html
https://social.technet.microsoft.com/Forums/en-US/e655c45f-3a74-4acb-8df1-3607e4fe6b49/issue-with-installing-linux-subsystem?forum=winserverhyperv
https://community.oracle.com/mosc/discussion/3949381/yum-update-error-rhn-plugin-network-error-connection-reset-by-peer