Self-hosted service
swoole/docker-swoole avatar
swoole/docker-swoole

docker-swoole: the official Swoole image, and the details its tags hide

🏄 Official Docker Image of Swoole

566 stars116 forksDockerfileApache-2.0

At a glance

What is it?
The Swoole project's Docker image layers Swoole on top of the official PHP image with rebuild and Supervisord scripts, dev tooling for reload and debugging, and a matrix of versioned and nightly tags whose extension contents differ. It suits a PHP team running Swoole in containers, and the Redis serializer support varies by tag in ways the documentation spells out.
Who is it for?
docker-swoole is worth using if you run Swoole in containers, because the image is maintained by the Swoole project itself and therefore tracks the extension's releases rather than lagging behind them, because the rebuild script means you can build a specific Swoole version yourself instead of waiting for a tag, and because the debugging examples cover gdb, valgrind, strace, blackfire and xdebug out of the box. It is the wrong tool if you only need PHP in a container.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Dockerfile, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The official PHP image with Swoole compiled in

The phpswoole/swoole image is the official Docker image of Swoole, and its relationship to the official PHP image is the first thing to understand. The documentation says it is built using the official PHP image as its base image, with a few changes, and that for basic usage you should read the description of the official PHP image, because everything about running a PHP container in general still applies.

That is a sensible design decision rather than a shortcut. The official PHP image already solves the awkward parts of a PHP container, the entrypoint behaviour, the environment variable conventions, the helper scripts, the way extensions are configured at build time, and the practice of removing the source tarball and the build dependencies from the final layer. By starting from it, the Swoole image inherits that behaviour and only has to add the parts specific to Swoole.

The feature list describes what it adds. Built-in scripts to rebuild Swoole and to manage Supervisord programs. Easy management of booting scripts in Docker. The ability to run PHP scripts and other commands directly in different environments, including ECS. One root filesystem for simplicity, which the documentation explains as one Docker COPY command only in the dockerfiles. Composer included, with Composer v1 for Swoole 4.5.8 and before and Composer v2 for 4.5.9 and after. Support for several architectures. Support for auto-reloading for local development, and support for code debugging for local development.

The one root filesystem point is worth a second look, because it is the difference between an image that behaves predictably when you mount a volume and one that does not. If the extension, the configuration and the runtime files all live under a single directory that the image copies in one step, then mounting a volume over that directory is the supported way to override behaviour, and the scripts can find what they need at a predictable path.

The image is published on Docker Hub as phpswoole/swoole, the licence is Apache 2.0, and the repository is the swoole organisation's docker-swoole project, with the last push on 2026-09-25. The repository tree is the build system itself, with dockerfiles/ for the per-version definitions, rootfilesystem/ for the files copied into the image, config/ and templates/ for the configuration, src/ and bin/ for the scripts, and a config.yml at the top level that appears to drive the generation of those.

Adding extensions, and the -dev package trap in newer images

Most PHP extensions are installed the same way as in the official PHP image, using the helper scripts docker-php-ext-configure, docker-php-ext-install, docker-php-ext-enable and docker-php-source, and the documentation gives three worked examples.

For the MySQL extensions:

Dockerfile
# To install the MySQL extensions.
# NOTE: The pdo_mysql extension is included in 4.8.12+ and 5.0.1+ images.
FROM phpswoole/swoole:4.7-php7.4-alpine

RUN docker-php-ext-install mysqli pdo_mysql

For Redis, the example installs the extension through PECL and then enables it:

Dockerfile
RUN set -ex \
    && pecl channel-update pecl.php.net \
    && yes no | pecl install redis-stable \
    && docker-php-ext-enable redis

And the Couchbase example shows the fuller pattern on Alpine, with apk for the runtime library, a virtual .build-deps package for the headers, pecl for the extension itself, and then a cleanup that removes the build dependencies, the apk cache, the temporary files, the man pages and the PHP source tarball. That last line is the difference between an image that is a few hundred megabytes and one that is a few dozen.

The recent change to be aware of is in the -dev packages. Nightly images and 6.3.0+ images no longer come with the -dev packages that earlier images happened to leave behind, such as libgmp-dev, libldap-dev, libkrb5-dev and libzstd-dev, so a command like docker-php-ext-install gmp ldap now needs a preceding apt-get install -y libgmp-dev libldap-dev.

That is a small change with a disproportionate effect on anyone upgrading, because the failure is not an error you recognise. The extension install fails with a missing header, and the natural reading is that the image is broken, when in fact the image is tidier than it was and the build now has to say what it needs.

The Redis serializer matrix, which is where tag choice gets tricky

The extension Redis is compiled with the msgpack serializer disabled. The igbinary serializer is enabled in nightly images and in versioned images since 6.3.0, which include the igbinary extension for that purpose, while in earlier versioned images it is disabled. The lzf and zstd compressions are enabled in nightly images and in versioned images since 6.1.10 and 6.2.2, and in earlier versioned images no compression is available.

So the Redis capabilities vary across the tag list in a way that has nothing to do with the Swoole version, and that is the trap. A team picks a tag because it wants Swoole 6.1 or 6.2, and their caching code uses the igbinary serializer or zstd compression, and the image they chose does not have it. The Swoole version and the extension capabilities are two different axes of the same tag.

The documentation gives you a way to check, which is the right answer to a matrix like this:

bash
# Tag "php8.4" is a nightly image.
docker run --rm phpswoole/swoole:php8.4 php --ri redis | grep Available

and the expected output is:

code
Available serializers => php, json, igbinary
Available compression => lzf, zstd

Running that on the tag you actually plan to use takes a few seconds and settles the question.

The second half of the Redis story is about runtime behaviour rather than build time. Serializers and compressions are opt-in at runtime: Redis::OPT_SERIALIZER defaults to Redis::SERIALIZER_NONE and Redis::OPT_COMPRESSION defaults to Redis::COMPRESSION_NONE, so none of them changes how your data is stored unless your application asks for it.

That is the correct default, and it also means a change in the image can be invisible until you opt in. Enabling igbinary in a new tag and not in an old one changes the wire format your existing data uses once you switch the option on, so a mixed fleet of tags talking to one Redis instance can read data written by another only if the serialization options agree.

There is a documented procedure for the older images. To use Redis::SERIALIZER_IGBINARY in images older than 6.3.0, or the msgpack serializer in any image, the Redis extension has to be rebuilt against igbinary or msgpack, and installing igbinary alone is not enough: helper scripts such as install-php-extensions skip extensions that are already installed, so the bundled Redis extension is left untouched. You have to remove it first and then reinstall both.

Coroutines, c-ares and the rest of the feature notes

The other two substantive feature notes concern the Swoole build itself rather than PHP extensions.

Swoole is built with c-ares for asynchronous DNS resolution in coroutines, in nightly images and in 6.3.0+ images. That is a meaningful difference for anyone using coroutines, because the default resolver in a coroutine context can block the whole worker, whereas a c-ares based resolver does the lookup asynchronously. An image with it and an image without it behave differently under a DNS-heavy workload even though the Swoole version is the same.

The second is the pdo_mysql and Redis extension inclusion. Both are included since 4.8.12 and 5.0.1, and the notes point at the section on disabling installed or enabled PHP extensions for the two cases where you do not want them in the image. That is a feature worth pausing on: a general purpose image that ships with a MySQL driver and a Redis driver baked in is convenient, and it is also a supply chain surface that an organisation with a policy on included drivers will want to control.

The auto-reload feature is supported for non-Alpine images only, and the same restriction applies to the code debugging support listed in the feature list. The repository ships examples for both, in the 00-autoreload directory and in the debugging set, 30-debug-with-gdb, 31-debug-with-valgrind, 32-debug-with-strace, 33-debug-with-blackfire and 34-debug-with-xdebug.

The rest of the example directory is a catalogue of the image's features as runnable cases: 00-autoreload, 01-basic, 02-www, 03-nginx, 04-entrypoint, 05-boot, 06-update-token, 07-disable-default-server, 10-install-php-extension, 11-customize-extension-options, 12-php.ini, then a series of Supervisord examples from 20-supervisord-services through 24-supervisord-gracefully-shutdown, and then the debugging set. Each numbered directory is a self-contained example, which is a better way to learn an image than a page of prose about it.

The tag matrix and how the images are built

The documentation organises the published images into two families, and the distinction is about how much risk you take on.

The versioned images are based on stable releases of Swoole, and the documentation lists them per release line: Swoole 6.3, 6.2, 6.1, 6.0, 5.1, 5.0 and 4.8, with a Dockerfile link for each. The nightlies are built daily using the master branch of swoole-src.

Daily builds are the interesting end of that spectrum. A nightly image is the extension's current master, compiled, published and available the next morning, which means it carries whatever was merged the day before. That is useful for testing an upcoming release and for reporting a bug against code that is not released yet, and it is a poor choice for production.

The tag naming follows the shape the PHP images use, with the Swoole version, the PHP version and the base distribution in one tag, which is why the extension examples in the documentation use tags like 4.7-php7.4-alpine and 4.8-php7.4-alpine. A single tag therefore encodes three decisions: which Swoole, which PHP, and which base image family, and the Alpine and Debian variants of the same Swoole line differ in which packages are available and in whether the auto-reload feature works.

The images can also be built manually, which the documentation has a section for, and the repository layout supports that with the dockerfiles/ directory holding the per-version definitions and the rootfilesystem/ directory holding what gets copied in. The build system has a config.yml, a src/ directory and a bin/ directory, plus tests/, a phpunit.xml.dist, a .php-cs-fixer.dist.php for style, a composer.json and a CHANGELOG.md, so the generation of the image definitions is itself a tested piece of software rather than a pile of hand-maintained Dockerfiles.

Where the Swoole image is the wrong tool

The first limit is that it is a general purpose image, and general purpose means it carries things you may not want. The documentation says so itself. The pdo_mysql and Redis extensions are present by default, and although there is a documented way to disable them, an image that starts from the official PHP base and adds an extension is a larger artefact than one built for your application, and the whole point of the general purpose image is that it is not tailored.

The second is the tag matrix. The choice is not one dimension but three, Swoole line, PHP line and base distribution, and the capabilities inside the image, the Redis serializers, the compression algorithms, the c-ares resolver, the presence of the -dev packages, the auto-reload feature, all vary across that matrix. A team that picks a tag in a hurry can end up with an image that does not do what the code expects, and the fix is not always obvious from the symptom.

The third is that the debugging and reload features are development conveniences that change the image's behaviour. An image with auto-reload watches the filesystem, and an image configured for gdb or xdebug has the debugging tooling present. Those are fine on a laptop and wrong on a production host, and the documentation does not make the separation for you.

The fourth is that a container image is a delivery format, not a deployment strategy. Swoole is a coroutine server and its usual deployment story involves process managers, multiple workers and a reverse proxy, which is what the Supervisord examples and the 03-nginx example are about. The image gives you the runtime and the tooling; the process supervision, the log routing and the restart policy are still yours to configure.

And the fifth is the project dependency. The image is maintained by the Swoole project, which is a good sign for its currency, but it is a separate artefact from the extension, published on a different cadence, and the nightlies track a moving master branch. If your deployment depends on a specific Swoole build, the versioned tags give you a stable reference, and the build-your-own route in the repository gives you one you control.

Editorial conclusion

docker-swoole is worth using if you run Swoole in containers, because the image is maintained by the Swoole project itself and therefore tracks the extension's releases rather than lagging behind them, because the rebuild script means you can build a specific Swoole version yourself instead of waiting for a tag, and because the debugging examples cover gdb, valgrind, strace, blackfire and xdebug out of the box. It is the wrong tool if you only need PHP in a container. Before you pick a tag, check three things: which extension features you need are present, because the Redis extension arrives with the igbinary serializer in nightly and 6.3.0+ images but not in earlier versioned images, and lzf and zstd compression appears only in nightly images and in 6.1.10+ and 6.2.2+, so a tag chosen for its Swoole version may not match your caching code; that the auto-reload feature is only supported on non-Alpine images, so a development setup on Alpine will not get it; and that the -dev packages earlier images happened to leave behind are gone in nightly and 6.3.0+ images, so a command like docker-php-ext-install gmp ldap now needs a preceding apt-get install of the matching -dev packages.

Frequently asked questions

How do I install a PHP extension in the Swoole Docker image?

Use the same helper scripts as the official PHP image, docker-php-ext-configure, docker-php-ext-install, docker-php-ext-enable and docker-php-source, and install the -dev packages an extension is built against first. Nightly and 6.3.0+ images no longer ship those -dev packages, so docker-php-ext-install gmp ldap now needs a preceding apt-get install -y libgmp-dev libldap-dev.

Which Redis serializers and compressions does a given Swoole image support?

The Redis extension is always compiled with msgpack disabled. The igbinary serializer is enabled in nightly images and in versioned images since 6.3.0, and the lzf and zstd compressions are enabled in nightly images and in versioned images since 6.1.10 and 6.2.2. You can check a specific image with docker run --rm phpswoole/swoole:php8.4 php --ri redis | grep Available.

Does the Swoole Docker image support auto-reload and code debugging?

The feature list includes support for auto-reloading for local development and support for code debugging for local development, and the auto-reloading feature is supported for non-Alpine images only. The repository ships worked examples for gdb, valgrind, strace, blackfire and xdebug, along with a series of Supervisord examples for services, tasks and graceful shutdown.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. Project website
  4. README
  5. swoole/docker-swoole on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/swoole-docker-swoole.svg)](https://hysenlabs.com/projects/swoole-docker-swoole)

Was this useful?