Local AWS S3 for PHP Symfony development with Docker

Stefan Pöltl
2 min readSep 13, 2023

In this post I’m going to show you the simplest way to develop AWS S3 related software locally. Adobe created a lightweight server for this usecase that exposes the most common API functionality. You can easily integrate it in your local development stack via a Docker image that has the footprint of around 70 MB.

Docker setup

As usual for Docker based development you have two options to start the S3 Server:

  1. Run the container with plain Docker command:
docker run -p 9090:9090 -p 9191:9191 -e initialBuckets=my-bucket -t adobe/s3mock

2. Run the container with docker compose:

services:
s3mock:
image: adobe/s3mock
environment:
- initialBuckets=my-bucket
ports:
- 9090:9090
- 9191:9191

Basically the HTTP port 9090 is enough for local development purposes. The other one (9191) works for HTTPS.

Install AWS SDK

All we really need to execute S3 API calls is the AWS PHP SDK:

composer require aws/aws-sdk-php

Let’s try a basic test script with the list buckets command:

<?php

require_once __DIR__ . '/vendor/autoload.php';

putenv("AWS_ACCESS_KEY_ID=id");
putenv("AWS_SECRET_ACCESS_KEY=key");

$s3client = new \Aws\S3\S3Client([
'version' => 'latest',
'endpoint' => 'http://localhost:9090',
'region' => 'eu-central-1',
'use_path_style_endpoint' => true
]);


$result = $s3client->listBuckets();
var_dump($result->toArray()['Buckets']);

One issue with the AWS PHP SDK is that it doesn’t support the AWS_ENDPOINT_URL env variable, so you have to pass the endpoint yourself. Here is the current overview of SDKs supporting this ENV variable:

https://docs.aws.amazon.com/sdkref/latest/guide/feature-ss-endpoints.html

For production environments you can pass something like this endpoint for a bucket. Just replace $REGION with your bucket region:

https://s3.$REGION.amazonaws.com

Configure Symfony Service

To get a working S3 client in Symfony you can simply add it in your services.yml like this and you’re good to go:

Aws\S3\S3Client:
class: Aws\S3\S3Client
arguments:
- version: 'latest'
region: '%env(AWS_REGION)%'
endpoint: '%env(S3_ENDPOINT)%'

Yes you need to pass a region, otherwise the service will tell you that it’s missing :D

Now you are able to inject the S3 client into every autowired class like this:

public function __construct(
private S3Client $s3Client
)
{
}

Summary

Thank you adobe for this simple S3 compatible server that eases local development and integration testing in your continuous integration environment.

--

--