Laravel 12 Queue Jobs Tutorial with Docker (Step-by-Step from Scratch)
Laravel 12: Tutorials, Guides & Best Practices
Author
Richard Mendes
June 15, 2026 • 15 mins

Laravel 12 Queue Jobs Tutorial with Docker (Step-by-Step from Scratch)

A complete guide to setting up Laravel 12 queues with Docker, jobs, and background processing.

Before we start creating jobs in Laravel 12, let's set up a local development environment using Docker. This approach allows us to run Laravel, MySQL, and phpMyAdmin in isolated containers without installing them directly on our machine.

For this tutorial, we'll use three services:

  1. app – Runs our Laravel application
  2. mysql – Stores our application data
  3. phpMyAdmin – Provides a web interface for managing the database

Create a docker-compose.yml file in the root of your project and add the following configuration:

services:
app:
build: .
container_name: laravel12_app_container
volumes:
- .:/var/www
ports:
- "8000:8000"
depends_on:
- mysql
command: php -S 0.0.0.0:8000 -t /var/www

mysql:
image: mysql:8.0
container_name: laravel12_mysql_container
restart: always
environment:
MYSQL_ROOT_PASSWORD: mysqlroot
MYSQL_DATABASE: jobs_db
MYSQL_USER: testuser
MYSQL_PASSWORD: testpass
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql

phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: laravel12_phpmyadmin_container
restart: always
ports:
- "8080:80"
environment:
PMA_HOST: mysql
PMA_USER: testuser
PMA_PASSWORD: testpass
depends_on:
- mysql

volumes:
mysql_data:


Now that we have defined our application services, we need to create a Docker image for the Laravel application.

Create a Dockerfile in the root of your project and add the following configuration:

This image uses PHP 8.3 and installs the extensions required by Laravel, including MySQL support, file handling, image processing, and queue-related functionality. It also installs Composer so we can manage our project's dependencies directly from within the container.

FROM php:8.3-cli

RUN apt-get update && apt-get install -y \
git \
unzip \
zip \
libzip-dev \
libpng-dev \
libjpeg-dev \
libfreetype6-dev \
libonig-dev \
libxml2-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install \
bcmath \
gd \
mbstring \
opcache \
pdo \
pdo_mysql \
pcntl \
zip

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

WORKDIR /var/www

Now that both docker-compose.yml and Dockerfile are ready, we need to build our Docker images and start the containers.

Build the Docker containers

Run the following command to build the application image:

docker compose build

This command reads the Dockerfile and installs all required dependencies inside the image, including PHP extensions and Composer.

Start the containers

Once the build is complete, start all services using:

docker compose up

Installing Laravel 12 inside Docker

Now that our Docker containers are running, the next step is to install Laravel 12 inside the application container.

Since we are using Docker Desktop, everything runs inside our app container.

Inside the container, run the following command:

composer create-project laravel/laravel:^12.0 jobs-app

We specify :^12.0 to ensure we are installing Laravel 12 explicitly.

This tells Composer to install Laravel in the current directory (/var/www/jobs-app), which is already mapped to our local project folder.

Verify installation

After installation completes, your project structure should look like this:

app/

bootstrap/

config/

database/

routes/

artisan

At this point, Laravel 12 is successfully installed inside our Docker environment.

Open the application

Visit:

http://localhost:8000/jobs-app/public/index.php

You should now see the Laravel welcome page running from Docker.

Update .env Settings

DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=jobs_db
DB_USERNAME=testuser
DB_PASSWORD=testpass

Also change

QUEUE_CONNECTION=sync

Change it to

QUEUE_CONNECTION=database

Run Artisan Migration Commands

php artisan queue:table
php artisan migrate

Because Laravel needs this table:

jobs
failed_jobs

jobs table stores jobs that are waiting to be executed.Think of it like Jobs in line, waiting for the worker to pick them up.

failed_jobs table stores jobs that crashed or failed permanently. Think of it as Jobs that could not be processed successfully.

Creating a Controller and Route in Laravel 12

Now that Laravel is installed inside our Docker container, we will create a controller and a route to trigger our job later.

This will act as the entry point where we dispatch our background job.

Inside the Docker container, under jobs-app and run:

php artisan make:controller TransactionController

This will create:

app/Http/Controllers/ProductController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Jobs\StoreProductJob;

class ProductController extends Controller
{
public function process_product()
{
StoreProductJob::dispatch();
}
}

Define the route

Open routes/web.php and add:

<?php

use App\Http\Controllers\ProductController;
use Illuminate\Support\Facades\Route;


Route::get('/', function () {
return view('welcome');
});

Route::get('/process-product', [ProductController::class, 'process_product']);

Create a Job using Laravel Artisan Command

php artisan make:job StoreProductJob

You will see a file in app/Http/Jobs

<?php

namespace App\Jobs;

use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;

class StoreProductJob implements ShouldQueue
{
use Queueable;

/**
* Create a new job instance.
*/
public function __construct()
{
//
}

/**
* Execute the job.
*/
public function handle(): void
{
//
}
}

Dispatching and Running Jobs in Laravel 12

Now that we have created our job (StoreProductJob), let’s understand how to dispatch and execute it.

In Laravel, dispatching a job does not run it immediately. Instead, it pushes the job into a queue, and a background worker processes it.

Run this url

http://localhost:8000/jobs-app/public/index.php/process-product

When this method is called:

  1. The job is added to the queue
  2. It is stored in the jobs table (if using database queue)
  3. It does NOT execute immediately

Check the image below

Run the Queue Worker

To actually process the job, we need to start the queue worker.

Inside your Docker container, run:

php artisan queue:work

This command continuously listens for new jobs and executes them.

Popular Posts

Comments (0)

No comments yet. Be the first to comment!

Latest Articles