The Oracle XE database is for test and development purposes.

Oracle Database XE Release 21c is the developer edition of the industry-leading relational database server. The Oracle XE Database server Docker image contains Oracle Database Express Edition Release 21c (21.3.0.0) running on Oracle Linux 7. This image contains a default database in a multitenant configuration with one pluggable database.

WARNING: The maximum amount of user data in an Oracle Database XE database cannot exceed 12 GB.

How to run a docker container for your development, and test environments

You should choose a disk where you have enough memory to save the data files of your database. In the following example I choose the disk D: and the following directory tree:

D:/docker/oracle_xe/
                    |__dmp
                    |__oradata
                    |__scripts
                              |__setup
                                     |__ 1_preparedb.sql
                                     |__ 2_create_schema.sql

In the setup folder you can add the following scripts to initialize your database:

-- 1_preparedb.sql 

ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;

alter user system identified by oraclepwd;
alter session set container=XEPDB1;
create directory FILER_REFRESH as '/dmp';

-- inutile de creer le tempfile car par defaut un est créé et nommé temp
-- create temporary tablespace temp TEMPFILE '/opt/oracle/oradata/XE/XEPDB1/temp.dbf' size 200M AUTOEXTEND ON NEXT 50M MAXSIZE 3G;
create tablespace DATA DATAFILE '/opt/oracle/oradata/XE/XEPDB1/data01.dbf' size 2G AUTOEXTEND ON NEXT 100M MAXSIZE 30G;
alter tablespace DATA add DATAFILE '/opt/oracle/oradata/XE/XEPDB1/data02.dbf' size 2G AUTOEXTEND ON NEXT 100M MAXSIZE 15G;
create tablespace IDX DATAFILE '/opt/oracle/oradata/XE/XEPDB1/index01.dbf' size 2G AUTOEXTEND ON NEXT 100M MAXSIZE 30G;
-- 2_create_schema.sql
alter session set container=XEPDB1;

-- create user &1 identified by "&2" default tablespace data TEMPORARY TABLESPACE temp;
-- if you don't indicate TEMPORARY tablespace the default temporary tablespace will be taken (generally the default one is TEMP)
create user ORHDOCKER identified by "ORHDOCKER" default tablespace DATA TEMPORARY TABLESPACE TEMP;
grant connect,resource to ORHDOCKER ;
grant unlimited tablespace to ORHDOCKER ;
grant execute on dbms_pipe to ORHDOCKER ;
grant execute on dbms_lock to ORHDOCKER ;
grant create any table,create any view, create any procedure to ORHDOCKER ;

COMMIT;
docker login container-registry.oracle.com

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

docker run -d --name myOracleXeDevDB -p 51521:1521 -p 55500:5500 -e ORACLE_PWD=oraclepwd -e ORACLE_CHARACTERSET=WE8ISO8859P15 -v D:\docker\oracle_xe\dmp:/dmp -v D:\docker\oracle_xe\scripts\setup:/docker-entrypoint-initdb.d/setup -v D:\docker\oracle_xe\oradata:/opt/oracle/oradata container-registry.oracle.com/database/express:21.3.0-xe

by default ORACLE_SID=XE (not changeable, this option only exist in enterprise image)

ORACLE_PDB=XEPDB1 (not changeable, this option only exist in enterprise image)

To see the logs of your container and follow the start:

docker logs myOracleXeDevDB

→ wait for 5 minutes until the database creation is complete

NOTE (troubleshoot) : some symbols doesn’t seem to be accepted in the ORACLE_PWD option, for instance these two values were causing an infinite error log “Password cannot be null. Enter password:”

  • ORACLE_PWD=”MyOraPwd1++”
  • ORACLE_PWD=MyOraPwd1++

And in the case of this error in the D:/docker/dockoracle1/oradata we can see that nothing is created/written

Connecting from Within the Container

You can connect to the Oracle Database server by running a SQL*Plus command from within the container using one of the following commands:

docker exec -it <oracle-db> /bin/bash
docker exec -it <oracle-db> sqlplus / as sysdba
docker exec -it <oracle-db> sqlplus / as sysdba
docker exec -it <oracle-db> sqlplus sys/<your_password>@XE as sysdba
docker exec -it <oracle-db> sqlplus system/<your_password>@XE
docker exec -it <oracle-db> sqlplus pdbadmin/<your_password>@XEPDB1

Fully clean your oracle container

docker stop myOracleXeDevDB
docker rm myOracleXeDevDB

And then go to your host volume that mapped /opt/oracle/oradata, here it’s D:\docker\oracle_xe\oradata

Empty this directory, otherwise, even if you have removed the container, when you will run your container with the same volumes mapping it will reuse the oradata found.

Quickier creation of oracle container

We can almost speak about a speed light creation so much the classic creation time is long.

You simply have to copy paste the content of an existing oradata volume into a new directory of your host. And run your container with the volume /opt/oracle/oradata mapped by this new directory. Your container will detect it and will not create all the database datafiles and configuration files (.ora files). And these files took very long to be created.

Oracle Enterprise Manager Express

The XE image comes with Oracle Enterprise Manager Express

https://localhost:55500/em

Create your own docker image in order to personalize it

FROM container-registry.oracle.com/database/express:21.3.0-xe 
# ==> Oracle server express edition => WARNING: The maximum amount of user data in an Oracle Database XE database cannot exceed 12 GB.

USER root
RUN yum -y install vim mlocate wget && \
    yum clean all

RUN echo "## Colorize the ls output ##" >> /etc/profile && \
    echo "alias ls='ls --color=auto'" >> /etc/profile && \
    echo "## Use a long listing format ##" >> /etc/profile && \
	echo "alias ll='ls -la'" >> /etc/profile


# export PS1 is to change prompt color when logged as oracle user.
USER oracle
WORKDIR /home/oracle
RUN echo "export ORACLE_HOME=/opt/oracle/product/21c/dbhomeXE" >> .bash_profile && \
    echo "export PATH=\$PATH:\$ORACLE_HOME/bin" >> .bash_profile && \
    echo "export LD_LIBRARY_PATH=\$ORACLE_HOME/lib:/lib:/usr/lib" >> .bash_profile && \
    echo "export CLASSPATH=\$ORACLE_HOME/jlib:\$ORACLE_HOME/rdbms/jlib" >> .bash_profile && \
    echo "export PS1='\[\033[02;32m\]\u@\H:\[\033[02;37m\]]\w\\$\[\033[44m\]\${ORACLE_SID}\[\033[00m\]'" >> .bash_profile

Then build your image, open a terminal and go to the folder containing this Dockerfile:

docker build -f Dockerfile -t dockoracle:v1.0 .

Output:

$> docker build -f Dockerfile -t dockoracle:v1.0 .
[+] Building 69.1s (9/9) FINISHED
 => [internal] load .dockerignore                                                                                  0.1s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load build definition from Dockerfile                                                               0.2s
 => => transferring dockerfile: 1.15kB                                                                             0.0s
 => [internal] load metadata for container-registry.oracle.com/database/express:21.3.0-xe                          0.0s
 => [1/5] FROM container-registry.oracle.com/database/express:21.3.0-xe                                            0.2s
 => [2/5] WORKDIR /home/oracle                                                                                     0.1s
 => [3/5] RUN echo "export ORACLE_HOME=/opt/oracle/product/21c/dbhomeXE" >> .bash_profile &&     echo "export PAT  0.7s
 => [4/5] RUN yum -y install vim mlocate wget &&     yum clean all                                                43.5s
 => [5/5] RUN echo "## Colorize the ls output ##" >> /etc/profile &&     echo "alias ls='ls --color=auto'" >> /et  0.7s
 => exporting to image                                                                                             1.1s
 => => exporting layers                                                                                            1.1s
 => => writing image sha256:aa119663ebffd49cd5779b1d6a8134208a39a26f5b311298b458cd98d7932211                       0.0s
 => => naming to docker.io/library/dockoracle:v1.0

Then still in the same folder (the containing the Dockerfile), create the previous directory structure:

In your folder you have:

Dockerfile
oracle_xe/
         |__dmp
         |__oradata
         |__scripts
                  |__setup
                         |__ 1_preparedb.sql
                         |__ 2_create_schema.sql

Now create a container from your image, like this (WARNING: I intentionally changed the port mapping to avoid conflicts with the previous example):

docker run -d --name myOwnOracleXeDevDB -p 50521:1521 -p 50500:5500 -e ORACLE_PWD=oraclepwd -e ORACLE_CHARACTERSET=WE8ISO8859P15 -v .\oracle_xe\dmp:/dmp -v .\oracle_xe\scripts\setup:/docker-entrypoint-initdb.d/setup -v .\oracle_xe\oradata:/opt/oracle/oradata dockoracle:v1.0

Then use docker logs <yourcontainer_id> to follow the creation of your container (take some time, because some big files are created the first you launch it):

$> docker run -d --name myOwnOracleXeDevDB -p 50521:1521 -p 50500:5500 -e ORACLE_PWD=oraclepwd -e ORACLE_CHARACTERSET=WE8ISO8859P15 -v .\oracle_xe\dmp:/dmp -v .\oracle_xe\scripts\setup:/docker-entrypoint-initdb.d/setup -v .\oracle_xe\oradata:/opt/oracle/oradata dockoracle:v1.009b379e4f4cc1fef4ff8fcb86af2396142c4b68aa928f4cf6d4713f9fec18676

C:\Users\nfourniol\Documents\dev\dockoracle>docker logs 09b379e4f4cc1fef4ff8fcb86af2396142c4b68aa928f4cf6d4713f9fec18676
Specify a password to be used for database accounts. Oracle recommends that the password entered should be at least 8 characters in length, contain at least 1 uppercase character, 1 lower case character and 1 digit [0-9]. Note that the same password will be used for SYS, SYSTEM and PDBADMIN accounts:
Confirm the password:
Configuring Oracle Listener.
Listener configuration succeeded.
Configuring Oracle Database XE.
Enter SYS user password:
***********
Enter SYSTEM user password:
**********
Enter PDBADMIN User Password:
********
Prepare for db operation
7% complete
Copying database files

$> docker logs 09b379e4f4cc1fef4ff8fcb86af2396142c4b68aa928f4cf6d4713f9fec18676
Specify a password to be used for database accounts. Oracle recommends that the password entered should be at least 8 characters in length, contain at least 1 uppercase character, 1 lower case character and 1 digit [0-9]. Note that the same password will be used for SYS, SYSTEM and PDBADMIN accounts:
Confirm the password:
Configuring Oracle Listener.
Listener configuration succeeded.
Configuring Oracle Database XE.
Enter SYS user password:
***********
Enter SYSTEM user password:
**********
Enter PDBADMIN User Password:
********
Prepare for db operation
7% complete
Copying database files
...
... (here some more logs)
...
/opt/oracle/runUserScripts.sh: running /opt/oracle/scripts/setup/2_create_user_orhus.sql

Session altered.


User created.


Grant succeeded.


Grant succeeded.


Grant succeeded.


Grant succeeded.


Grant succeeded.


Grant succeeded.


Commit complete.



DONE: Executing user defined scripts

The Oracle base remains unchanged with value /opt/oracle
#########################
DATABASE IS READY TO USE!
#########################
The following output is now a tail of the alert.log:
2023-09-13T07:36:39.589174+00:00
XEPDB1(3):create tablespace DATA DATAFILE '/opt/oracle/oradata/XE/XEPDB1/data01.dbf' size 2G AUTOEXTEND ON NEXT 100M MAXSIZE 30G
2023-09-13T07:37:01.430270+00:00
XEPDB1(3):Completed: create tablespace DATA DATAFILE '/opt/oracle/oradata/XE/XEPDB1/data01.dbf' size 2G AUTOEXTEND ON NEXT 100M MAXSIZE 30G
XEPDB1(3):alter tablespace DATA add DATAFILE '/opt/oracle/oradata/XE/XEPDB1/data02.dbf' size 2G AUTOEXTEND ON NEXT 100M MAXSIZE 15G
2023-09-13T07:37:25.454860+00:00
XEPDB1(3):Completed: alter tablespace DATA add DATAFILE '/opt/oracle/oradata/XE/XEPDB1/data02.dbf' size 2G AUTOEXTEND ON NEXT 100M MAXSIZE 15G
XEPDB1(3):create tablespace IDX DATAFILE '/opt/oracle/oradata/XE/XEPDB1/index01.dbf' size 2G AUTOEXTEND ON NEXT 100M MAXSIZE 30G
2023-09-13T07:37:52.004514+00:00
XEPDB1(3):Completed: create tablespace IDX DATAFILE '/opt/oracle/oradata/XE/XEPDB1/index01.dbf' size 2G AUTOEXTEND ON NEXT 100M MAXSIZE 30G

ORA-01017: invalid username/password; logon denied

This error happens during the execution of the setup scripts you’ve mentioned to your container. It happened because in your Dockerfile you probably switched the user to root.

For instance, this simple Dockerfile will cause the error:

FROM container-registry.oracle.com/database/express:21.3.0-xe 
# ==> Oracle server express edition => WARNING: The maximum amount of user data in an Oracle Database XE database cannot exceed 12 GB.

USER root # switch to root user and no switch back to oracle user will cause the error mentioned

docker: Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:50521 -> 0.0.0.0:0: listen tcp 0.0.0.0:50521: bind: An attempt was made to access a socket in a way forbidden by its access permissions.

The solution:

net stop winnat
netsh int ipv4 set dynamic tcp start=50000 num=10000
netsh int ipv6 set dynamic tcp start=50000 num=10000
net start winnat

Source: https://github.com/docker/for-win/issues/3171#issuecomment-788808021