Moving PHP 8.2 + OCI8 to a Docker-Based PHP 8.3 Setup

Recently I had a task where we needed to upgrade an Apache 2.4 server running PHP 8.2 with the OCI8 extension connected to an Oracle backend. The existing setup was RPM-based on RHEL, using Remi packages, and getting OCI8 working had previously required manual handling of the Oracle Instant Client libraries.

It worked — but it was fragile.

When planning the move to PHP 8.3 (and possibly a new AlmaLinux 10 server), I started asking myself: should we really go through the same OS-bound dependency alignment again?

The Problem

The current setup required:

  • Manual removal and reinstallation of oracle-instantclient
  • Matching the correct libclntsh.so version
  • Updating php82-php-oci8
  • Making sure system libraries aligned with the OS version

It worked, but it wasn’t reproducible. Rebuilding this on a new server would mean repeating the same careful sequence again.

The Idea

Instead of upgrading the OS stack and PHP modules directly, I decided to containerize the setup:

  • php:8.3-apache as base image
  • Install Oracle Instant Client inside the container
  • Compile and enable OCI8 in the image
  • Expose Apache on port 8083
  • Restrict access using iptables to the internal network

The goal was simple:
Make the environment portable, reproducible, and independent of the host OS.

What We Did

  1. Built a custom Docker image with PHP 8.3 + OCI8.
  2. Installed Oracle Instant Client during the image build.
  3. Exposed the container on port 8083.
  4. Restricted access to 129.177.0.0/16 using iptables.
  5. Mounted the application files using a bind mount instead of copying them into the container.

The bind mount was important. Copying files into a running container works — until the container is recreated. Using a host-mounted directory ensures the application survives rebuilds.

The Result

The container is now:

  • Running PHP 8.3 with OCI8
  • Fully isolated from host OS library conflicts
  • Easy to rebuild
  • Easy to roll back
  • Cleaner from an operational perspective

Most importantly: upgrading PHP in the future will now mean changing a base image tag and rebuilding — not re-engineering system libraries.

This small migration significantly reduced long-term operational risk.

FROM php:8.3-apache

# Install required system dependencies
RUN apt-get update && apt-get install -y \
    libaio1t64 \
    libaio-dev \
    unzip \
    build-essential \
    && rm -rf /var/lib/apt/lists/* \
    && ln -s /usr/lib/x86_64-linux-gnu/libaio.so.1t64 /usr/lib/x86_64-linux-gnu/libaio.so.1

# Copy Oracle Instant Client packages (download manually first)
COPY instantclient-basic-linux.x64-23.26.1.0.0.zip /tmp/
COPY instantclient-sdk-linux.x64-23.26.1.0.0.zip /tmp/

# Extract Oracle Instant Client Basic
RUN mkdir -p /opt/oracle && \
    unzip -q /tmp/instantclient-basic-linux.x64-23.26.1.0.0.zip -d /opt/oracle

# Extract Oracle Instant Client SDK (force overwrite with -o)
RUN unzip -qo /tmp/instantclient-sdk-linux.x64-23.26.1.0.0.zip -d /opt/oracle

# Create symlink and cleanup
RUN ln -s /opt/oracle/instantclient_23_26 /opt/oracle/instantclient && \
    rm /tmp/*.zip

# Configure library path
ENV LD_LIBRARY_PATH=/opt/oracle/instantclient
ENV ORACLE_HOME=/opt/oracle/instantclient

# Install OCI8 extension
RUN docker-php-ext-configure oci8 --with-oci8=instantclient,/opt/oracle/instantclient \
    && docker-php-ext-install oci8 \
    && docker-php-ext-enable oci8

# Enable Apache modules if needed
RUN a2enmod rewrite

RUN chown -R www-data:www-data /var/www/html

# Expose port
EXPOSE 80

Leave a Reply

Your email address will not be published. Required fields are marked *