Btrfs to overlay2 storage driver


With the latest version 23.0 docker has removed support for the btrfs storage driver.

So I would like to move to overlay2 as it seems to be the recommended path so we can continue to receive updates. Our application is a single container running various apps within.

I reviewed the official documentation it states to modify /etc/docker/daemon.json and switch it from btrfs to overlay2. I’ve been playing around with this and have had no success.

Below is what I have tried and the problems encountered.

I also included docker version and docker info output.

In my last attempt, this is what I tried:

  1. Save Image: docker save image:latest | gzip > image_latest.tar.gz
  2. Copy contents (a mount on our FS): cp -au /var/lib/docker /var/lib/docker.bk
  3. stop docker
  4. Modify daemon.json to overlay2
  5. start docker
  6. Load Image: docker load --input image_latest.tar.gz

At this point, the image reloads but when i run docker ps -a nothing is running. When i try docker run to start the image, I do get a few errors.

[root@server ~]# docker run image:latest

/usr/lib/python2.7/site-packages/supervisor/ UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a “-c” argument specifying an absolute path to a configuration file for improved security.

'Supervisord is running as root and it is searching ’

Error: The directory named as part of the path /opt/app/external/logs/proftpd/proftpdCtl.out does not exist in section ‘program:proftpd’ (file: ‘/etc/supervisord.d/supervisord.ini’)

At this point I get some results when checking docker ps -a, but the name associated (boring_lumiere) is random and not the name of the container.


02df591c1cae ecentre:latest “/bin/sh -c '/usr/bi…” 13 minutes ago Exited (2) 13 minutes ago boring_lumiere

Results of docker info and version prior to any changes.

[root@server ~]# docker info


Context: default

Debug Mode: false


app: Docker App (Docker Inc., v0.9.1-beta3)

buildx: Docker Buildx (Docker Inc., v0.9.1-docker)

scan: Docker Scan (Docker Inc., v0.17.0)


Containers: 1

Running: 1

Paused: 0

Stopped: 0

Images: 1

Server Version: 20.10.18

Storage Driver: btrfs

Build Version: Btrfs v4.9.1

Library Version: 102

Logging Driver: json-file

Cgroup Driver: cgroupfs

Cgroup Version: 1


Volume: local

Network: bridge host ipvlan macvlan null overlay

Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog

Swarm: inactive

Runtimes: runc io.containerd.runc.v2 io.containerd.runtime.v1.linux

Default Runtime: runc

Init Binary: docker-init

containerd version: 9cd3357b7fd7218e4aec3eae239db1f68a5a6ec6

runc version: v1.1.4-0-g5fd4c4d

init version: de40ad0

Security Options:


Profile: default

Kernel Version: 3.10.0-1160.83.1.el7.x86_64

Operating System: CentOS Linux 7 (Core)

OSType: linux

Architecture: x86_64

CPUs: 2

Total Memory: 7.56GiB

Name: xxx


Docker Root Dir: /var/lib/docker

Debug Mode: false



Experimental: false

Insecure Registries:

Live Restore Enabled: false

WARNING: bridge-nf-call-iptables is disabled

WARNING: bridge-nf-call-ip6tables is disabled

Thank you if you read this and any future input.

The Docker Engine 23.0 release notes say:

  • Promote overlay2 to be the default storage driver (btrfs and zfs are now opt-in). moby/moby#42661

Now you need to specifically enable the btrfs storage driver in /etc/docker/deamon.json (create file if not exists):

  "storage-driver": "btrfs"

Though, I remember another use had problems with btrfs. Generally overlay2 is the most reliable and performant storage drivers, so migrating to overlay2 on the long term, is probably not a bad idea.

Judging by your post, you already did that. I doubt that it’s possible to create a consistent backup copy using the 2nd command.

docker save/ docker load = export/import image, not containers!
docker exports / docker import = export/import containers as tarballs

If persistent data is stored in volumes outside containers, there is no need to export containers.
Depenending whether you used named volumes, you might want to backup their content. If you use binds, you don’t need to do anything, as it’s already stored in folder on the host filesystem.

Self made images can be re-created. Images can be pulled from DockerHub. In theory you would only need to save old images from dockerhub where the tag doesn’t exist online in dockerhub anymore - but honestly who would want to do that?!


Thanks for your input. The release notes are not entirely clear to me, but it seems they have completely removed the btrfs driver. Although the github/moby link indicates that they are “opt-in”.

Is the “opt-in” defined by configuring daemon.json file to use btrfs? If so, that is what is configured.

Upon running dockerd the output shows:

INFO[2023-02-28T12:33:54.234061712-05:00] [graphdriver] trying configured driver: btrfs
WARN[2023-02-28T12:33:54.234240377-05:00] Unable to locate plugin: btrfs, retrying in 1s
WARN[2023-02-28T12:33:55.234794264-05:00] Unable to locate plugin: btrfs, retrying in 2s
WARN[2023-02-28T12:33:57.235034286-05:00] Unable to locate plugin: btrfs, retrying in 4s
WARN[2023-02-28T12:34:01.235277013-05:00] Unable to locate plugin: btrfs, retrying in 8s
ERRO[2023-02-28T12:34:09.235552949-05:00] Failed to GetDriver graph driver=btrfs error=“Error looking up graphdriver plugin btrfs: plugin "btrfs" not found” home-dir=/var/lib/docker
INFO[2023-02-28T12:34:09.235917439-05:00] [core] [Channel #1] Channel Connectivity change to SHUTDOWN module=grpc
INFO[2023-02-28T12:34:09.235950310-05:00] [core] [Channel #1 SubChannel #2] Subchannel Connectivity change to SHUTDOWN module=grpc
INFO[2023-02-28T12:34:09.235968215-05:00] [core] [Channel #1 SubChannel #2] Subchannel deleted module=grpc
INFO[2023-02-28T12:34:09.235975941-05:00] [core] [Channel #1] Channel deleted module=grpc
failed to start daemon: error initializing graphdriver: driver not supported