nicolasff / webdis

A Redis HTTP interface with JSON output
https://webd.is
BSD 2-Clause "Simplified" License
2.82k stars 307 forks source link

Recovery using .rdb file in docker container #228

Closed lorenzoc25 closed 1 year ago

lorenzoc25 commented 1 year ago

Hi, Seems like there's not a lot of documentation when operating webdis inside docker container, so I opened this issue. What I'm trying to do is to recover the data inside redis by using a .rdb file and then served them through webdis running inside a docker container, but I couldn't find a way to achieve it. I've tried to go to the webdis container and search for /var/redis/<PORT_NUMBER> directory and place the .rdb file there, but I couldn't find the directory inside it. What should I do then to recover the data from a .rdb file inside the container?

nicolasff commented 1 year ago

Hi Lorenzo,

Sorry I'm only getting to this now. What you need to do here mostly has to do with configuring Redis rather than Webdis (granted this is the Redis instance that's in the Webdis container).

I'll try to explain this in a way that follows the steps I took to get there, so that hopefully it's not a matter of you just blindly copying a command. For this I'll be using the latest tag of Webdis, which is currently the same image as 0.1.20.

The first thing we need to figure out is where Redis stores its data. An easy way to explore the Docker image is just to use it to run a shell:

$ docker run --rm -ti nicolas/webdis:latest /bin/sh

From there we can find the Redis config file and see how it persists data:

$ grep '^dir' /etc/redis.conf
dir /var/lib/redis

We could also have done all this with a single command:

$ docker run --rm -ti nicolas/webdis:latest cat /etc/redis.conf | grep ^dir
dir /var/lib/redis

In order to have access to /var/lib/redis from the host, we can run the Docker container with a mounted volume such that a local directory on the host (we'll call it redis-data) will be accessible as /var/lib/redis from inside the container. So let's create this directory, run Webdis with the mount, write a couple of keys, save the .rdb, and stop the container:

$ mkdir ./redis-data

$ docker run -d --rm --name webdis-local -v$(pwd)/redis-data:/var/lib/redis \
     -p127.0.0.1:7379:7379 nicolas/webdis:latest
f95a587c644a7b8b838eee2ac60b9bb92613e3aa4a5cc6347ca61fdce324c477

$ curl -s http://127.0.0.1:7379/PING
{"PING":[true,"PONG"]}
$ curl -s http://127.0.0.1:7379/SET/hello/world
{"SET":[true,"OK"]}
$ curl -s http://127.0.0.1:7379/SET/foo/bar
{"SET":[true,"OK"]}
$ curl -s http://127.0.0.1:7379/SAVE
{"SAVE":[true,"OK"]}

$ ls redis-data/
dump.rdb
$ docker stop webdis-local
webdis-local

We now have dump.rdb in our local directory, we can verify that it contains the keys we've just written:

$ xxd redis-data/dump.rdb
00000000: 5245 4449 5330 3030 39fa 0972 6564 6973  REDIS0009..redis
00000010: 2d76 6572 0536 2e32 2e36 fa0a 7265 6469  -ver.6.2.6..redi
00000020: 732d 6269 7473 c040 fa05 6374 696d 65c2  s-bits.@..ctime.
00000030: 5765 dc62 fa08 7573 6564 2d6d 656d c281  We.b..used-mem..
00000040: a00e 00fa 0c61 6f66 2d70 7265 616d 626c  .....aof-preambl
00000050: 65c0 00fe 00fb 0200 0005 6865 6c6c 6f05  e.........hello.       <--- hello…
00000060: 776f 726c 6400 0366 6f6f 0362 6172 ffaf  world..foo.bar..       <--- …:world and foo:bar
00000070: ebb4 9ade 2632 58                        ....&2X

We've now stopped the container, and it was removed since we had started it with --rm; indeed we can't restart it:

$ docker start webdis-local
Error response from daemon: No such container: webdis-local
Error: failed to start containers: webdis-local

Now if we start a new Webdis container – let's call it webdis-new – with the same command line except for --name, again mounting our local redis-data directory as /var/lib/redis but this time with a dump.rdb file inside, then we should expect this data to be available immediately:

$ docker run -d --rm --name webdis-new -v$(pwd)/redis-data:/var/lib/redis \
    -p127.0.0.1:7379:7379 nicolas/webdis:latest
4002cf5a699150875efa445a1e862865886b2515bbab6ad1d556ebd5f0234ae1

$ curl -s http://127.0.0.1:7379/GET/hello
{"GET":"world"}
$ curl -s http://127.0.0.1:7379/GET/foo
{"GET":"bar"}

$ docker stop webdis-new
webdis-new

This shows that we successfully re-imported dump.rdb as the source data that Redis will start with in a new container.

I hope this helps!

lorenzoc25 commented 1 year ago

Thank you so much for the detailed explanation! Yes I did not just simply copy the command but I was instead trying to follow the pattern on the own server but seems like the config was set differently. I did look through redis' docker documentation and they didn't mention the way to recover .rdp file so I really appreciate that you were able to help me! Thank you again and wish this issue could help more people like me!

nicolasff commented 1 year ago

@lorenzoc25 Great! I'm glad this was useful. As you wrote, the point was also to help others who might be in the same situation. There have been a few questions in the past on how to configure Webdis where I converted an answer I gave on GitHub to dedicated docs, and I think I'll do the same here.

nicolasff commented 1 year ago

Update: this is now a dedicated article in the docs. Thanks for the question!