MTITEK.com
Oracle Database / Install Oracle XE on Windows (WSL 2 + Docker)

References:
https://learn.microsoft.com/en-us/windows/wsl/install
https://docs.docker.com/desktop/features/wsl/
https://container-registry.oracle.com (database/express)
https://www.oracle.com/tools/downloads/sqldev-downloads.html

Install Windows Subsystem for Linux (WSL 2)

WSL 2 is a full Linux kernel built by Microsoft, allowing Linux containers to run natively without emulation.

Requirements: Windows 11
To check your system type run systeminfo | find "System Type".
To check your Windows version press Windows logo key + R, type winver, select OK.

Recommended Installation (Windows 11)

Open PowerShell as Administrator and run:

wsl --install

This enables all required features, installs the WSL 2 kernel, sets version 2 as default, and installs Ubuntu.
Restart when it finishes, then create your Linux user account and password.

Verify the Installation

Confirm that your distro runs version 2: Docker Desktop integration only works with WSL 2 distros:

wsl -l -v
  NAME      STATE           VERSION
* Ubuntu    Running         2

Configure Global Options with .wslconfig

To limit the memory and CPU that WSL 2 can use, create the file C:\Users\<yourUserName>\.wslconfig.
By default WSL 2 can use up to 50% of the host RAM. Oracle XE needs at least 2 GB for itself, so do not set the limit below 4 GB when running the database:

[wsl2]
memory=4GB    # Limits VM memory in WSL 2
processors=2  # Makes the WSL 2 VM use two virtual processors

Run wsl --shutdown to apply the settings.
See https://learn.microsoft.com/en-us/windows/wsl/wsl-config#configure-global-options-with-wslconfig for all options.

SSH into WSL 2 from a Remote Machine

These port-forwarding steps are only needed if you want to reach your WSL 2 distro from another machine. (e.g., expose the Oracle listener port 1521).
References: https://learn.microsoft.com/en-us/windows-server/networking/technologies/netsh/netsh-interface-portproxy
https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/netsh-advfirewall-firewall-control-firewall-behavior.

Port-Forwarding Steps

To remove the port-forwarding and firewall rule configurations:

C:\Users\mtitek>netsh advfirewall firewall delete rule name="Open Port 1521 - WSL 2"
C:\Users\mtitek>netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=1521

Install Docker Desktop with the WSL 2 Backend

Run Oracle XE on Docker

The official Oracle XE image is hosted on Oracle's container registry. Sign in once with your Oracle account (accept the database/express license terms on container-registry.oracle.com first), then pull and run:

$ docker login container-registry.oracle.com
$ docker pull container-registry.oracle.com/database/express:21.3.0-xe

$ docker run -d --name oracle-xe \
    -p 1521:1521 \
    -p 5500:5500 \
    -e ORACLE_PWD=SYSPWD \
    -v oracle-data:/opt/oracle/oradata \
    container-registry.oracle.com/database/express:21.3.0-xe
Check the logs to see when the database is ready to accept connections. You should see "DATABASE IS READY TO USE!" in the logs when it's ready.
$ docker logs -f oracle-xe

Check the Connection

The container exposes two services: XE (the CDB root, for admin connections) and XEPDB1 (the default pluggable database, for application connections).

Install Oracle SQL Developer

Download SQL Developer from https://www.oracle.com/tools/downloads/sqldev-downloads.html. Download the "Windows 64-bit with JDK included" version, unzip it, and run sqldeveloper.exe.

Create the admin connection in SQL Developer (CDB root): Username: sys, Password: SYSPWD, Hostname: localhost, Port: 1521, Service name: XE, Role: SYSDBA.

Create the Application Schema

Connect as sys and switch to the pluggable database XEPDB1.
application schemas must live in the PDB, never in the CDB root. The tablespace must exist before it can be referenced by CREATE USER:

ALTER SESSION SET CONTAINER = XEPDB1;

CREATE TABLESPACE MTITEK_DATA_TS DATAFILE '/opt/oracle/oradata/XE/XEPDB1/mtitek_data_ts_1.dbf' SIZE 500M AUTOEXTEND ON;

CREATE USER MTITEK_APP IDENTIFIED BY MTITEKPWD DEFAULT TABLESPACE MTITEK_DATA_TS QUOTA UNLIMITED ON MTITEK_DATA_TS;

GRANT CONNECT, RESOURCE TO MTITEK_APP;

MTITEK_APP is the schema/user.
MTITEK_DATA_TS is the tablespace that physically stores its data.

Create the application connection in SQL Developer: Username: MTITEK_APP, Password: MTITEKPWD, Hostname: localhost, Port: 1521, Service name: XEPDB1, Role: default.

Verify the schema with a first table:

CREATE TABLE MTITEK_TABLE (
    ID    NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    LABEL VARCHAR2(100) NOT NULL
);

INSERT INTO MTITEK_TABLE (LABEL) VALUES ('Hello Oracle!');
SELECT * FROM MTITEK_TABLE;