How to Successfully set up OpenClaw in Docker

I wanted to try out OpenClaw in my HomeLab and see if it can streamline my life a bit. There are a ton of use cases I have in mind, including monitoring the HomeLab, tie-ins with MQTT and Home Assistant, and automating the little daily things that consume time.

For an agentic system with this much potential control, I felt it imperative to secure it in a Docker container. I containerize pretty much all other major services anyway as it’s far easier to manage.

The Docker Problem Today

I came to find that OpenClaw is not an out-of-the box Docker installation. There is no stock image on dockerhub. Instead, you build you clone the repo and run a docker setup script.

There are a plethora of environment variables that can be set beforehand to try and tailor your installation. I was not comfortable with exporting sensitive items like api keys such that they are available for other apps on my Ubuntu VM. It felt really inconsistent as to where customizations are mastered (in .env? export variables?).

The script has a nice setup wizard which is ok for getting the gateway set up, including a step to select the skills you want to install. After upping the container the first time, I found that most skills either weren’t installable, or would not persist across rebuilds of the image.

I figured I did something wrong and re-ran the setup script, only to find it would wipe environment variables like OPENCLAW_DOCKER_APT_PACKAGES, and I just made things worse.

In the end, I was forced to understand the nuts and bolts of how it all worked in order to get a successful installation. In order for Skill installs to work at runtime from the GUI, you need to have the various runtime environments installed, and done so in a persistent manner. That does not work out-of-the box. gog presented difficulties too as it wasn’t clear where the keys need to be persisted, and what the correct step sequence was.

These are all early stage adoption problems that I’m sure will be sorted out over time. But in the meantime, I wanted to stick with the docker approach and decided to put together something that worked for me and that could be shared with others.

If you want to jump ahead, you can find a summary of my approach and the small set of files you need to get going with OpenClaw and Docker at Github openclaw-extensions.

The Approach

Dockerfile.local

I didn’t want to customize Dockerfile itself since that can get updated in the repo. I felt the better approach was to put my customizations in a Dockerfile.local, which inherits from the stock OpenClaw Dockerfile. This includes:
– Installation of user defined apt packages. The list is mastered here, instead of the environment OPENCLAW_DOCKER_APT_PACKAGES.
– Installation and set up of the runtime environments (npm/uv/go/brew) so that skills can install from the console/GUI at runtime and are persistent.
– Installation of user defined skills that I wanted, with priority given to binary installs I could bake into the image. This includes gog, goplaces, camsnap, etc. I also customized whisper to use the tiny model instead the of default 2 GB turbo model.

Docker Compose Override

To separate out my compose customizations, I created a docker-compose-override.yml. It includes:
– bind mount for linuxbrew so installs are persisted.
– bind mount for gog at /home/node/.config/gogcli so the file based keyring is persisted.
– environment variables for my integrations (in my case, HomeAssistant api token HA_TOKEN).

This override file is automatically combined with docker-compose.yml by compose.

Image Build Script

I wanted a 1 click re-build and update method to simplify things. I created docker-update.sh to manage the image build. I use this instead of running the OpenClaw docker-setup directly, which presents problems on updates. This also does a one-time install of linuxbrew if it is not yet present.

After modifying Dockerfile.local, e.g. for an additional install, just run ~/openclaw/docker-update.sh --build
This rebuilds the image and restarts the container.

Wrapup

It took me a couple of days to get my head around everything, but now I’m able to add Skills from the Console (including my own custom skills) easily update the image with additions, and focus on bringing OpenClaw to life.
If this works for you or helps you in any way, please like the repo.