Skip to content

Instantly share code, notes, and snippets.

@syahzul
Last active April 13, 2025 23:51
Show Gist options
  • Save syahzul/52a4a639befce5c614b349c1f5403dd0 to your computer and use it in GitHub Desktop.
Save syahzul/52a4a639befce5c614b349c1f5403dd0 to your computer and use it in GitHub Desktop.
Laravel Sail with Ubuntu 24.04, PHP8.3 and Oracle OCI8

Laravel Sail with Ubuntu 24.04, PHP8.3 and Oracle OCI8

Note:

This is a work in progress and may not work correctly. Proceed with caution.

Tested Platforms

✅ macOS Sequoia 15.3 (Apple M1)
✅ macOS Monterey 12.7 (Intel Core i7)

Preparation

Navigate to your Laravel application folder:

cd ~/Sites/my-laravel-app

Since Laravel includes Sail by default, install it using the following command:

php artisan sail:install

This will create a docker-compose.yml file in the root of your application folder. You will need to modify this file later.

docker-compose.yml

Edit the docker-compose.yml file and make the following changes:

services:
    laravel.test:
        build:
            context: './docker'
            dockerfile: Dockerfile
            args:
                WWWGROUP: '${WWWGROUP}'
        image: 'sail-8.3/app'
        extra_hosts:
            - 'host.docker.internal:host-gateway'
        ports:
            - '${APP_PORT:-80}:80'
            - '${VITE_PORT:-5173}:${VITE_PORT:-5173}'
        environment:
            WWWUSER: '${WWWUSER}'
            LARAVEL_SAIL: 1
            XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}'
            XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}'
            IGNITION_LOCAL_SITES_PATH: '${PWD}'
        volumes:
            - '.:/var/www/html'
        networks:
            - sail
        depends_on:
            - mysql
    mysql:
        image: 'mysql/mysql-server:8.0'
        ports:
            - '${FORWARD_DB_PORT:-3306}:3306'
        environment:
            MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ROOT_HOST: '%'
            MYSQL_DATABASE: '${DB_DATABASE}'
            MYSQL_USER: '${DB_USERNAME}'
            MYSQL_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ALLOW_EMPTY_PASSWORD: 1
        volumes:
            - 'sail-mysql:/var/lib/mysql'
            - './vendor/laravel/sail/database/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh'
        networks:
            - sail
        healthcheck:
            test:
                - CMD
                - mysqladmin
                - ping
                - '-p${DB_PASSWORD}'
            retries: 3
            timeout: 5s
networks:
    sail:
        driver: bridge
volumes:
    sail-mysql:
        driver: local

Sail Files

Copy the necessary files from Laravel Sail into the docker folder:

cp vendor/laravel/sail/runtimes/8.3/* docker

The following files will be copied:

  1. Dockerfile
  2. php.ini
  3. start-container
  4. supervisord.conf

Dockerfile

Modify the Dockerfile as follows:

FROM ubuntu:24.04

LABEL maintainer="Syahril Zulkefli"

ARG WWWGROUP
ARG NODE_VERSION=22
ARG MYSQL_CLIENT="mysql-client"
ARG POSTGRES_VERSION=17

# Change this to aarch64 for ARM or Apple Silicon, or x86_64 for Intel CPU
ARG ARCH=aarch64
ARG ORACLE_VERSION=23.7.0.25.01
ARG ORACLE_BASE_URL=https://download.oracle.com/otn_software/linux/instantclient/2370000

WORKDIR /var/www/html

ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Asia/Kuala_Lumpur
ENV SUPERVISOR_PHP_COMMAND="/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0 --port=80"
ENV SUPERVISOR_PHP_USER="sail"

ENV LD_LIBRARY_PATH=/opt/oracle/instantclient
ENV ORACLE_HOME=/opt/oracle/instantclient

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN echo "Acquire::http::Pipeline-Depth 0;" > /etc/apt/apt.conf.d/99custom && \
    echo "Acquire::http::No-Cache true;" >> /etc/apt/apt.conf.d/99custom && \
    echo "Acquire::BrokenProxy    true;" >> /etc/apt/apt.conf.d/99custom

RUN apt-get update && apt-get upgrade -y \
    && mkdir -p /etc/apt/keyrings \
    && apt-get install -y libaio-dev wget gnupg gosu curl ca-certificates zip unzip git supervisor sqlite3 libcap2-bin libpng-dev python3 dnsutils librsvg2-bin fswatch ffmpeg nano  \
    && curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xb8dc7e53946656efbce4c1dd71daeaab4ad4cab6' | gpg --dearmor | tee /etc/apt/keyrings/ppa_ondrej_php.gpg > /dev/null \
    && echo "deb [signed-by=/etc/apt/keyrings/ppa_ondrej_php.gpg] https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \
    && apt-get update \
    && apt-get install -y php8.3-cli php8.3-dev \
       php8.3-pgsql php8.3-sqlite3 php8.3-gd \
       php8.3-curl php8.3-mongodb \
       php8.3-imap php8.3-mysql php8.3-mbstring \
       php8.3-xml php8.3-zip php8.3-bcmath php8.3-soap \
       php8.3-intl php8.3-readline \
       php8.3-ldap \
       php8.3-msgpack php8.3-igbinary php8.3-redis \
       php8.3-memcached php8.3-pcov php8.3-imagick php8.3-xdebug php8.3-swoole \
    && curl -sLS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer \
    && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
    && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_VERSION.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \
    && apt-get update \
    && apt-get install -y nodejs \
    && npm install -g npm \
    && npm install -g pnpm \
    && npm install -g bun \
    && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /etc/apt/keyrings/yarn.gpg >/dev/null \
    && echo "deb [signed-by=/etc/apt/keyrings/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \
    && curl -sS https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/keyrings/pgdg.gpg >/dev/null \
    && echo "deb [signed-by=/etc/apt/keyrings/pgdg.gpg] http://apt.postgresql.org/pub/repos/apt noble-pgdg main" > /etc/apt/sources.list.d/pgdg.list \
    && apt-get update \
    && apt-get install -y yarn \
    && apt-get install -y $MYSQL_CLIENT \
    && apt-get install -y postgresql-client-$POSTGRES_VERSION \
    && apt-get -y autoremove \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

# Create Oracle directory and set up instant client
# Please note that if your computer is using ARM processor, you'll need Instant Client for ARM as well.
# But when pushing it to your server, the architecture might changed.
RUN mkdir -p /opt/oracle/instantclient && \
    if [ "$ARCH" = "aarch64" ]; then \
        ARCH_SUFFIX="arm64"; \
    else \
        ARCH_SUFFIX="x64"; \
    fi && \
    cd /opt/oracle/instantclient && \
    BASIC_ZIP="instantclient-basic-linux.${ARCH_SUFFIX}-${ORACLE_VERSION}.zip" && \
    SDK_ZIP="instantclient-sdk-linux.${ARCH_SUFFIX}-${ORACLE_VERSION}.zip" && \
    echo "Downloading ${ORACLE_BASE_URL}/${BASIC_ZIP}" && \
    wget --verbose -O "${BASIC_ZIP}" "${ORACLE_BASE_URL}/${BASIC_ZIP}" && \
    echo "Downloading ${ORACLE_BASE_URL}/${SDK_ZIP}" && \
    wget --verbose -O "${SDK_ZIP}" "${ORACLE_BASE_URL}/${SDK_ZIP}" && \
    echo "Unzipping ${BASIC_ZIP}" && \
    unzip -o "${BASIC_ZIP}" && \
    echo "Unzipping ${SDK_ZIP}" && \
    unzip -o "${SDK_ZIP}" && \
    mv instantclient_23_7/* . && \
    rm -rf instantclient_23_7 && \
    rm "${BASIC_ZIP}" "${SDK_ZIP}" && \
    ls -la /opt/oracle/instantclient

RUN echo /opt/oracle/instantclient > /etc/ld.so.conf.d/oracle-instantclient.conf \
    && ldconfig \
    && pecl channel-update pecl.php.net \
    && echo instantclient,/opt/oracle/instantclient | pecl install oci8 \
    && echo 'extension = oci8.so' > /etc/php/8.3/cli/conf.d/99-oci9.ini

# # Reference: https://askubuntu.com/questions/1511776/ubuntu-24-04-php-8-3-oci8-and-libaio-so-1/1514001#1514001
RUN ln -s /usr/lib/$ARCH-linux-gnu/libaio.so.1t64 /usr/lib/$ARCH-linux-gnu/libaio.so.1

RUN setcap "cap_net_bind_service=+ep" /usr/bin/php8.3

RUN userdel -r ubuntu
RUN groupadd --force -g $WWWGROUP sail
RUN useradd -ms /bin/bash --no-user-group -g $WWWGROUP -u 1337 sail

COPY start-container /usr/local/bin/start-container
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY php.ini /etc/php/8.3/cli/conf.d/99-sail.ini
RUN chmod +x /usr/local/bin/start-container

EXPOSE 80/tcp

ENTRYPOINT ["start-container"]

Boot up

Start your application in Docker using Sail:

./vendor/bin/sail up

Note

If you change the domain in docker-compose.yml, for example to my-new-domain.test, update your .env file with the following:

APP_SERVICE=my-new-domain.test

Don't forget to add your domain in your host file.

macOS & Linux

sudo echo '127.0.0.1    my-new-domain.test' >> /etc/hosts

To do:

  1. Support SSL, refer here.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment