Published: 2026-10-14

How to Run Oracle Database on a Mac (Apple Silicon) in 2026

Oracle ships no macOS build of Oracle Database, so on a Mac you run it as a Linux container. Since Oracle Database 23.5 Free there is an Arm64 Linux build, and the gvenzl/oracle-free image — Oracle AI Database 26ai Free, release 23.26.3 at the time of writing — runs on Apple Silicon without Rosetta. On an M4 Max it accepted connections a median of 20 seconds after docker run and held about 2.5 GiB of memory. Connect to localhost:1521/FREEPDB1: the service name is where most first connections go wrong. Among new Jam SQL Studio installations over six weeks, 42% of those that tried to reach an Oracle database never connected, against 17% for SQL Server, and “service not registered with the listener” was the most common error. Below: the commands, what we measured, and what each error means.

The short version

docker run -d --name oracle \
  -p 1521:1521 \
  -e ORACLE_PASSWORD=ChangeMe_2026 \
  -e APP_USER=app -e APP_USER_PASSWORD=App_2026 \
  -v oracle-data:/opt/oracle/oradata \
  gvenzl/oracle-free:23.26.3

docker logs -f oracle      # wait for: DATABASE IS READY TO USE!

Then connect any client with these values:

FieldValue
Host / portlocalhost / 1521
Service nameFREEPDB1 (not FREE, XE, XEPDB1 or ORCL)
Application userapp / App_2026 — created in FREEPDB1 by APP_USER
Admin usersystem / the ORACLE_PASSWORD value
EZConnect stringlocalhost:1521/FREEPDB1
JDBC URLjdbc:oracle:thin:@//localhost:1521/FREEPDB1

The tag is pinned on purpose. latest pointed at the same image (digest 7ed34d0ade89) when we checked on October 14, 2026, but it moves with every release, and a later docker pull would change the database version under you. The rest of this guide explains each part of that command and what happens when one of them is missing.

Pick a container runtime

The image is an ordinary OCI image, so Docker Desktop, Colima and Podman all run it with the same arguments. Every number in this post comes from Docker Desktop 4.54.0 on an M4 Max; we did not repeat the runs on Colima or Podman. Two things differ between them, and both are about the Linux VM the runtime starts:

  • Memory. The container used about 2.5 GiB once the database was open (more on that below), and its startup script prints a warning when it sees less than 2 GB. Colima’s default VM has 2 GiB of memory, per its README, which leaves nothing for anything else — start it with colima start --memory 4. On Podman, stop the machine and run podman machine set --memory 4096. In Docker Desktop the limit is under Settings → Resources.
  • CPU architecture. Leave it alone. All three pick the arm64 variant of a multi-arch image on an M-series Mac. Don’t add --platform linux/amd64 (or create a Colima VM with --arch x86_64) because an old tutorial did — the next section shows what that costs.

What runs on Apple Silicon without emulation

Oracle’s Database Free page says Mac developers “using Arm-based or Intel-based computers” can run Oracle AI Database 26ai Free “using a Docker image”. The gvenzl/oci-oracle-free README dates the change: Oracle has provided Arm ports since Oracle Database 23.5 Free, and the images have been multi-arch since then. Older editions never got an Arm64 build. We read each image’s manifest on October 14, 2026:

ImageDatabaseArchitecturesOn an M-series Mac
gvenzl/oracle-free (all tags: regular, -slim, -full, -faststart)26ai Free, 23.26.3amd64, arm64Runs as arm64
container-registry.oracle.com/database/free26ai Free (Oracle’s own image)amd64, arm64Runs as arm64
gvenzl/oracle-xe (11g, 18c, 21c)Express Edition; last image update October 2024amd64 onlyx86-64 emulation
container-registry.oracle.com/database/express21c Express Editionamd64 onlyx86-64 emulation

Oracle’s Enterprise Edition images sit behind a registry sign-in and licence acceptance, so we did not check them. On the Docker Desktop setup above, an amd64 container ran under Rosetta: /proc/cpuinfo inside it reported the vendor VirtualApple.

To see what emulation costs, we ran the amd64-only tag 23.26.3-slim-amd64 with --platform linux/amd64 and compared it with the arm64 23.26.3-slim on the same Mac. We did not run the XE images themselves; the amd64 build of the same Free release is the closest like-for-like comparison. Under Rosetta the database started without errors, ready in 22.1 and 31.1 seconds over two runs, against a 17.0-second median for the arm64 slim tag; with the spread we saw between runs, two runs cannot show whether emulation slows startup. The difference showed once it was running:

Measurementarm64 (-slim)amd64 under Rosetta (-slim-amd64)
PL/SQL loop, 20 million iterations2.59 s5.27 s
Insert 1 million generated rows0.76 s1.25 s
Container memory while idle2.06 GiB3.37–3.48 GiB
CPU while idleabout 1%about 2%

Times are medians of three runs, measured with SQL*Plus SET TIMING ON. Twice the CPU time for PL/SQL and over 1 GiB more memory is tolerable for a quick test, but there is no reason to accept it when an arm64 image exists. There is also a deadline: Apple’s September 1, 2026 developer notice says macOS 27 is the final release to support Rosetta for Intel apps. It does not mention the Rosetta for Linux that Docker Desktop uses here, so treat an emulated Oracle as a stopgap rather than a setup to build on.

Which image flavor to use

The gvenzl image comes in four flavors with the same database inside. We pulled the 23.26.3 tags and timed fresh containers from docker run to the DATABASE IS READY TO USE! line in the log, five runs each:

TagDownloadOn diskReady after: median (range)Memory at ready
23.26.3 (regular; also latest)1.00 GB3.33 GB20.1 s (7.3–26.0, 5 runs)2.0 GiB
23.26.3-slim714 MB2.29 GB17.0 s (6.1–23.9, 5 runs)2.0 GiB
23.26.3-faststart1.49 GB7.11 GB, of which 3.33 GB is shared with the regular tag22.3 s (9.5–36.5, 6 runs)2.0 GiB
23.26.3-full2.01 GB (Docker Hub)not pullednot measured—
Existing container, docker stop then docker start——10.2 s (1 run; the stop took 2.5 s)—

The differences between flavors are smaller than the spread within each one. Almost all of that spread came from one step: the time between the log lines starting up Oracle Database... and ORACLE instance started., which took anywhere from 1.7 to 15 seconds from run to run with no pattern we could find. Unpacking the compressed datafiles, the step the faststart images exist to skip, took 3–5 seconds. Faststart saved neither time nor disk here: in the five faststart runs we logged phase by phase, the step from ORACLE instance started. to Database opened. took 8–22 seconds against about 2 for the other tags, and after one start the container’s writable layer measured 3.29 GB, the same as a regular container’s. That is consistent with the overlay filesystem copying each datafile out of the image layer the first time the database writes to it. On Docker Desktop, use the regular tag, or -slim for a smaller download if you only need relational features.

Per the image’s ImageDetails.md, the regular image already drops Java in the database, SQLcl, OLAP, Workspace Manager and the JDBC drivers; -slim also uninstalls Oracle Text, Spatial and Locator and the Multilingual Engine. We compared DBA_REGISTRY in the two: the regular container lists Oracle Text and Spatial as VALID, while the slim one has neither and shows Oracle XML Database as INVALID. Skip -slim if you use CONTAINS text searches, SDO_GEOMETRY or XML DB. Use -full only when you need a component the others removed. All flavors keep SQL*Plus, Data Pump (expdp/impdp) and SQL*Loader inside the container, which you can run with docker exec instead of installing them on the Mac.

FREE or FREEPDB1: the service name

Oracle Database Free is a container database (CDB) called FREE with one pluggable database (PDB) called FREEPDB1. Your tables belong in the PDB. The CDB root is for administration, and a user created in the PDB does not exist there. Here is what the listener inside a fresh container offers (docker exec oracle lsnrctl status):

Service "5a4ccb1829931092e0634d00010ab936" has 1 instance(s).
Service "FREE" has 1 instance(s).
Service "FREEXDB" has 1 instance(s).
Service "freepdb1" has 1 instance(s).

The long hexadecimal name is the PDB’s internal service and FREEXDB serves XML DB; neither is something you connect to. We then connected with node-oracledb 6.10 in Thin mode — the driver Jam SQL Studio uses — and with SQL*Plus inside the container, trying the names people copy from older tutorials:

Connect string (port 1521)Result
localhost:1521/FREEPDB1 or /freepdb1Connects to FREEPDB1; the service name is not case-sensitive
localhost:1521/FREEConnects system to CDB$ROOT; your application user gets ORA-01017
localhost:1521 (no service)Also lands in CDB$ROOT, because the listener’s DEFAULT_SERVICE_LISTENER is FREE
localhost:1521/XEPDB1, /XE, /ORCLPDB1NJS-518: cannot connect to Oracle Database. Service "XEPDB1" is not registered with the listener at host 127.0.0.1 port 1521. SQL*Plus reports the same as ORA-12514
SID=FREEPDB1 in a descriptorNJS-519: … SID "FREEPDB1" is not registered with the listener — FREEPDB1 is a service, not a SID
SID=FREE in a descriptorConnects, to CDB$ROOT

XEPDB1 and XE come from Oracle XE 18c/21c guides; ORCLPDB1 and ORCL from Enterprise Edition defaults. If you create your own PDB with the image’s ORACLE_DATABASE variable, its name becomes another service. When you are not sure, lsnrctl status inside the container is the authority. In Jam SQL Studio, the Discover button next to the service-name field asks the listener which of the common names are registered and lists them as pills you can click.

Create a user you can log in with

The APP_USER and APP_USER_PASSWORD variables create the user on first start. The image’s createAppUser script switches to FREEPDB1 and runs, in effect:

ALTER SESSION SET CONTAINER = FREEPDB1;
CREATE USER app IDENTIFIED BY "App_2026" DEFAULT TABLESPACE users QUOTA UNLIMITED ON users;
GRANT DB_DEVELOPER_ROLE TO app;

To add a user later, connect as system to FREEPDB1 and run the last two statements yourself. The grant is the part people get wrong. We created four users with different grants and logged in as each over Thin mode:

GrantsLogin to FREEPDB1
NoneORA-01045: Login denied. User NO_GRANTS does not have CREATE SESSION privilege.
RESOURCE onlyORA-01045 — RESOURCE holds 15 CREATE privileges for objects, but not CREATE SESSION
CONNECT onlyLogs in. In 26ai CONNECT is exactly CREATE SESSION and SET CONTAINER, so the user can log in but cannot create a table
DB_DEVELOPER_ROLELogs in. The role carries 14 system privileges, including CREATE SESSION and DEBUG CONNECT SESSION, plus the RESOURCE and CTXAPP roles

So ORA-01045 appears when the user was given object privileges, typically RESOURCE alone, and never CREATE SESSION. GRANT CONNECT, RESOURCE, the pair in many older guides, works; DB_DEVELOPER_ROLE, added in 23ai, is the single grant meant for application developers. The other common surprise is ORA-01017: invalid credential or not authorized; logon denied with the right password: the user lives in FREEPDB1 and the connection went to FREE, or to no service at all.

If you plan to read execution plans, watch sessions or step through PL/SQL, those need further grants such as SELECT ANY DICTIONARY and DEBUG ANY PROCEDURE; the reproducible Oracle workflow lists them against this same container.

Keep your data: volumes and restarts

Without a volume the database lives in the container’s writable layer. It survives docker stop and docker start — the users we had created were still there after a restart — but docker rm deletes it. Mount a named volume at /opt/oracle/oradata, as in the command at the top, and the data outlives the container. We checked the whole cycle:

  1. A first container on an empty volume took 7.9 seconds to become ready and left 3.1 GB in the volume.
  2. We added a row, removed the container with docker rm -f, and started a new one on the same volume with a different ORACLE_PASSWORD. It was ready in 5.1 seconds, and the row was there.
  3. The new password did not apply. The log said so:
    CONTAINER: database already initialized.
    CONTAINER: WARNING: $ORACLE_PASSWORD has been specified but the database is already initialized. The password will be ignored.
    Logging in as system with the new password returned ORA-01017; the old one still worked.
  4. The image’s own script changes it: docker exec oracle resetPassword NewPassword_2026 sets the SYS and SYSTEM passwords, and the new password worked straight away.

The same rule covers every variable the image reads (ORACLE_PASSWORD, APP_USER, ORACLE_DATABASE): they apply when the database is created, not on later starts. To begin again from scratch, remove the container and the volume (docker volume rm oracle-data).

Init scripts run once, as SYS, in the root container

Files in /container-entrypoint-initdb.d (.sql, .sql.gz, .sql.zip and .sh, in alphabetical order) run after the database is created. Two details trip people up, and we checked both with a volume and a script mounted from the Mac:

  • They run only when the database is created. On the first start our script ran; on the second container, reusing the volume, the log went straight from database already initialized to the startup scripts. Without a volume every new container creates a fresh database, so the scripts run each time. For something that must happen on every start, use /container-entrypoint-startdb.d instead — our script there ran on both starts.
  • .sql files run as SYS in the root container, not in FREEPDB1. The image runs them with sqlplus / as sysdba. Our script printed its container before and after switching:
    init script connected to: CDB$ROOT
    after ALTER SESSION: FREEPDB1
    A CREATE TABLE without the switch lands in the root container, where your application never looks.

So an init script for an application schema starts like this:

-- db/init/01_app_schema.sql
ALTER SESSION SET CONTAINER = FREEPDB1;

CREATE USER app IDENTIFIED BY "App_2026" DEFAULT TABLESPACE users QUOTA UNLIMITED ON users;
GRANT DB_DEVELOPER_ROLE TO app;

CREATE TABLE app.notes (
  id   NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  body VARCHAR2(100)
);

Per the README, a failing sourced .sh script, or an executable one that exits non-zero, stops the container and can leave the database half-initialized. With Docker Compose, the image’s healthcheck.sh lets an application container wait until the database, including your init scripts, is ready:

services:
  oracle:
    image: gvenzl/oracle-free:23.26.3
    ports:
      - "1521:1521"
    environment:
      ORACLE_PASSWORD: ChangeMe_2026
    volumes:
      - oracle-data:/opt/oracle/oradata
      - ./db/init:/container-entrypoint-initdb.d:ro
    healthcheck:
      test: ["CMD", "healthcheck.sh"]
      interval: 5s
      timeout: 5s
      retries: 30
  app:
    build: .
    depends_on:
      oracle:
        condition: service_healthy
volumes:
  oracle-data:

In the 23.26.3 image, healthcheck.sh returns a non-zero status while the container is still initializing or running scripts from either directory, and zero once FREEPDB1 is open read-write. We ran this file on the same Mac with a placeholder app container and the init script above: docker compose up -d --wait returned after 17.3 seconds, and the app container started about 15 seconds after the database container, once the database reported healthy.

Memory, CPU and disk

Oracle’s terms cap Oracle AI Database 26ai Free at 2 CPUs, 2 GB of RAM and 12 GB of user data, per the Database Free page. Inside the container we read the settings that implement it:

  • cpu_count = 2, which the gvenzl image sets explicitly.
  • A System Global Area of 1,603,392,144 bytes (about 1.5 GiB, from the startup log) and pga_aggregate_target = 512 MiB, with a 2 GiB pga_aggregate_limit.
  • docker stats showed about 2.0 GiB as the database opened and 2.50 GiB a few minutes later, flat for the next three minutes with the database idle and 1–5% CPU.
  • The datafiles take 3.1 GB under /opt/oracle/oradata after the first start, on top of the image itself (3.33 GB on disk for the regular tag).

We would give the runtime’s VM at least 4 GB, so the database’s 2.5 GiB leaves room for the VM itself and an application container next to it. The 12 GB data cap is the limit you are most likely to meet if you load a copy of a production database.

Connect from a client on the Mac

The container is a normal Oracle listener on localhost:1521, so the connection is the same for every tool:

  • SQL*Plus in the container: docker exec -it oracle sqlplus app/App_2026@FREEPDB1. The image’s tnsnames.ora defines the FREE and FREEPDB1 aliases, so the short form works there.
  • Drivers on the Mac: EZConnect localhost:1521/FREEPDB1 for node-oracledb and python-oracledb, jdbc:oracle:thin:@//localhost:1521/FREEPDB1 for JDBC. The Thin modes of the Node.js and Python drivers need no Oracle Instant Client; Oracle on Apple Silicon without Instant Client covers why that matters on an M-series Mac.
  • From another container: on a shared Docker network the host is the container name (oracle:1521/FREEPDB1), not localhost.

In Jam SQL Studio, Detect local databases (in the New Connection dialog, the command palette and the Saved Connections dialog) lists running gvenzl/oracle-* and Oracle-registry containers. For a gvenzl/oracle-free container it fills in localhost, the published port and FREEPDB1, and takes the user and password from APP_USER / APP_USER_PASSWORD, or system and ORACLE_PASSWORD when no app user is set. Detection reads /var/run/docker.sock, or DOCKER_HOST when it points at a unix:// socket; with a Colima or Podman socket elsewhere, type the values in by hand. The connections guide has the details.

Jam SQL Studio New Connection dialog on the Oracle form: Connect by EZConnect, a host, port 1521, the service name FREEPDB1 with a Discover button, and password authentication
The Oracle connection form. For the container, the host is localhost; Discover lists the service names the listener knows.

Connection errors and what they mean

Some of these errors are only a matter of timing. We started a container and, at the same moment, began logging in from the Mac with a Thin-mode client every quarter of a second. It got four different errors before the first successful login 8.6 seconds later:

AfterWhat the client gotWhat the container was doing
0.1 sNJS-500: connection to Oracle Database was closed or brokenDocker’s published port accepted the connection, but the listener inside had not started
3.9 sNJS-518: … Service "FREEPDB1" is not registered with the listenerListener running, database not yet started
6.9 sORA-01109: database not openInstance started, FREEPDB1 not yet open
8.3 sORA-01017: invalid credential or not authorized; logon deniedDatabase open, but the startup script had not yet applied ORACLE_PASSWORD
8.6 sConnectedThe log had just printed DATABASE IS READY TO USE!

So an NJS-518 or ORA-01017 in the first seconds after docker run says nothing about your settings. Wait for the ready line, then look at the table below.

ErrorCause with a local containerFix
NJS-503: connection could not be establishedNothing is published on that port: the container is not running, the -p mapping is different, or the port is wrongdocker ps and check the PORTS column
NJS-500: connection was closed or brokenThe port is published but the listener inside has not started, or the container is restartingdocker logs oracle; wait for the ready line
ORA-01109: database not openThe database is still startingWait for the ready line
NJS-518 / ORA-12514: service is not registered with the listenerWrong service name (XEPDB1, ORCL…), or the database is still startingUse FREEPDB1; wait for DATABASE IS READY TO USE!
NJS-519 / ORA-12505: SID is not registeredA service name entered as a SIDUntick Use SID, or use SERVICE_NAME= in the descriptor
ORA-01017: invalid credential or not authorizedWrong password; a PDB user connecting to FREE; a password changed with ORACLE_PASSWORD on an existing volume; or a login in the second before the startup script sets the passwordConnect to FREEPDB1; use resetPassword for system
ORA-01045: user does not have CREATE SESSION privilegeThe user has RESOURCE or object grants onlyGRANT DB_DEVELOPER_ROLE (or CREATE SESSION)

Three more Thin-mode errors showed up in our telemetry, but never against a local Free container, because they come from older or locked-down servers:

  • NJS-138: “connections to this database server version are not supported by node-oracledb in Thin mode”. The server is older than 12.1, typically 11g. No setting in a Thin-mode client changes that; the server needs an upgrade, or the connection needs a Thick-mode client with Oracle Client libraries.
  • NJS-116: “password verifier type 0x939 is not supported”. Per the node-oracledb troubleshooting guide, the account has only a 10G password verifier and Thin mode needs 11G or later; an administrator has to upgrade the verifier, which means resetting the password. Accounts in the container have 11G 12C verifiers, which we checked in DBA_USERS.PASSWORD_VERSIONS.
  • NJS-533: “Advanced Networking Option service negotiation failed. Native Network Encryption and DataIntegrity only supported in node-oracledb thick mode”. The server requires Oracle Native Network Encryption; Thin-mode clients need TLS instead.

For the full list of Oracle connection fixes Jam SQL Studio offers in the error notice — including Browse services on this listener… for NJS-518 — see Oracle connection issues in the docs.

What the telemetry shows

Jam SQL Studio sends anonymous events when a connection succeeds, when a connection test returns, and when a connection fails — with the engine and the driver’s error code, never the host, user or message. We followed every installation first seen between August 27 and October 7, 2026 until October 14, and counted those that tried an engine but never had a successful connection or connection test with it:

EngineNew installations that tried itNever connectedShare
SQL Server3015117%
MySQL / MariaDB175169%
PostgreSQL1091211%
Oracle984142%

Oracle is the outlier, and the sample is small: 98 installations, of which 25 were on macOS (15 of those never connected — too few to read much into). These are the Oracle error codes those 98 installations hit; one installation can appear under several codes:

CodeMeaningInstallationsOf which never connected
NJS-518Service not registered with the listener3514
NJS-138Server older than 12.11716
NJS-530Host name could not be resolved129
NJS-11610G-only password verifier1110
NJS-503Connection could not be established119
ORA-01017Invalid credential110
NJS-519SID not registered with the listener83
NJS-510 / NJS-511Connection timed out / refused by the listener7 / 64 / 4
NJS-515 / NJS-514Error in an Easy Connect string / syntax error in a connection string6 / 33 / 2
NJS-516 / NJS-520No tnsnames.ora folder set / file not found4 / 34 / 2
NJS-533Server requires Native Network Encryption33

Read plainly:

  • The service name is the most common stumble, and often a recoverable one. 35 installations hit NJS-518; 14 of them never connected, and the rest found the right name. A local container removes the guesswork because the name is fixed: FREEPDB1.
  • Wrong passwords get fixed. All 11 installations that saw ORA-01017 connected later.
  • Old servers are dead ends for a Thin-mode client. NJS-138, NJS-116 and NJS-533 together reached 31 installations, and 29 of those never connected. None of them can be fixed from the client side.

What the data cannot say is what each failing database was: a container on a laptop, a company server or a cloud instance. The error codes only tell us that the Oracle failures that end a trial are mostly about finding the database, not about the SQL client.

Methodology

  • Machine: Apple M4 Max with 128 GB of memory, macOS 26.5.2, Docker Desktop 4.54.0 (Engine 29.1.2, containerd image store) with a 16-CPU, 32 GB Linux VM. About 30 unrelated containers were running throughout, so treat the times as indicative of this machine, not as a benchmark.
  • Images: gvenzl/oracle-free tags 23.26.3, 23.26.3-slim, 23.26.3-faststart and 23.26.3-slim-amd64, pulled on October 14, 2026. Sizes are Docker’s CONTENT SIZE (download) and DISK USAGE columns.
  • Start time: wall-clock seconds from issuing docker run -d to the first log line DATABASE IS READY TO USE!, polled every 0.5 s; each run used a new container with no volume unless stated, removed afterwards, with a 20-second pause between runs. Memory is the docker stats figure.
  • Connection tests: node-oracledb 6.10.0 in Thin mode from the Mac, and SQL*Plus 23.26.3 inside the container. All test containers, users and the volume were deleted afterwards.
  • Telemetry: anonymous Jam SQL Studio events feature:connect (a successful connection from the app, not from the connection dialog), feature:connection_test_result (success or failure of the dialog’s test), connection:error and feature:connection_error_hint (engine and driver error code only). An installation is one anonymous device identifier; “new” means its first app:installed event fell between August 27 and October 7, 2026, and events were counted until October 14. Installations with telemetry turned off are not included. A narrower check — installations from September 30 that pressed Test connection — gave the same picture: 11 of 27 never connected to Oracle, against 6 of 50 for SQL Server.

Quick Answers

Short answers to common questions about running Oracle Database on a Mac.

Q: Can you run Oracle Database on a Mac?

A: Yes, in a Linux container. Oracle ships no macOS build of Oracle Database, but Oracle AI Database 26ai Free has an Arm64 Linux build, so on an Apple Silicon Mac the gvenzl/oracle-free image or Oracle's container-registry.oracle.com/database/free image runs in Docker Desktop or another container runtime without x86 emulation. On an M4 Max the database accepted connections a median of 20 seconds after docker run and used about 2.5 GiB of memory.

Q: Does Oracle Database run natively on Apple Silicon?

A: Oracle Database Free does, inside a Linux container. Oracle has provided Arm64 builds since Oracle Database 23.5 Free, and the gvenzl/oracle-free and container-registry.oracle.com/database/free images are multi-arch, so Docker runs the arm64 variant. Oracle XE images (gvenzl/oracle-xe and container-registry.oracle.com/database/express) are amd64 only and run under x86-64 emulation. In our test the amd64 build of the same Free release did run under Rosetta, but a PL/SQL loop took twice as long and the container used over 1 GiB more memory.

Q: What is the service name for Oracle Database Free in Docker?

A: FREEPDB1, the pluggable database, so the EZConnect string is localhost:1521/FREEPDB1. FREE is the root of the container database and is meant for administration; a user created in FREEPDB1 gets ORA-01017 there. XE, XEPDB1, ORCL and ORCLPDB1 belong to other editions and return NJS-518 or ORA-12514, service not registered with the listener.

Q: Why does a new Oracle user get ORA-01045 when logging in?

A: The user has no CREATE SESSION privilege. In Oracle Database 26ai the RESOURCE role grants privileges to create tables, views and other objects but not CREATE SESSION, so a user given only RESOURCE cannot log in. Grant DB_DEVELOPER_ROLE, which includes CREATE SESSION, or CONNECT, which in 26ai consists of CREATE SESSION and SET CONTAINER.

Q: Why didn't my script in /container-entrypoint-initdb.d run?

A: The gvenzl image runs those scripts only when it creates a new database. If the container reuses a volume that already holds one, the log says database already initialized and skips them. The scripts also run as SYS connected to the root container, CDB$ROOT, so a script that creates application objects must start with ALTER SESSION SET CONTAINER = FREEPDB1. Scripts in /container-entrypoint-startdb.d run on every start instead.

Q: How much memory does Oracle Database Free need on a Mac?

A: Give the container VM at least 4 GB. Oracle AI Database 26ai Free is limited to 2 GB of database memory, and in our measurement the container used about 2.5 GiB once it was open. The image warns at startup when it sees less than 2 GB, and Colima's default VM has 2 GiB, so start Colima with --memory 4 or raise the Podman machine's memory.

Q: Do I need Oracle Instant Client to connect to the container?

A: No. Thin-mode drivers such as node-oracledb and python-oracledb, the JDBC thin driver and Jam SQL Studio connect over TCP without Instant Client. SQL*Plus, Data Pump and SQL*Loader are inside the container and run with docker exec, for example docker exec -it oracle sqlplus app/App_2026@FREEPDB1.

Summary

On an Apple Silicon Mac, Oracle Database means a Linux container, and since 23.5 Free that container runs as arm64: gvenzl/oracle-free or Oracle’s own database/free image, about 20 seconds to a usable database on our M4 Max and about 2.5 GiB of memory. Connect to FREEPDB1, give your user DB_DEVELOPER_ROLE, mount a named volume if the data should outlive the container, and remember that init scripts run once, as SYS, in the root container. If the database you actually need is an older company server, the client side is covered in Oracle Database on Mac and Linux without an Oracle Client; for SQL Server the equivalent of this guide is How to Run SQL Server on a Mac.

An Oracle Client for Apple Silicon

Jam SQL Studio connects to Oracle 12.2 and later through the Thin driver, with no Instant Client: Object Explorer for packages and sequences, execution plans, schema and data compare, and a PL/SQL debugger. Free for personal use.

Related