This is a work in progress and may not work correctly. Proceed with caution.
✅ macOS Sequoia 15.3 (Apple M1)
✅ macOS Monterey 12.7 (Intel Core i7)
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.
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
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:
- Dockerfile
- php.ini
- start-container
- supervisord.conf
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"]
Start your application in Docker using Sail:
./vendor/bin/sail up
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.
sudo echo '127.0.0.1 my-new-domain.test' >> /etc/hosts
- Support SSL, refer here.