Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trouble connecting docker image to external redis server #232

Open
VagyokC4 opened this issue Apr 14, 2023 · 9 comments
Open

Trouble connecting docker image to external redis server #232

VagyokC4 opened this issue Apr 14, 2023 · 9 comments

Comments

@VagyokC4
Copy link

VagyokC4 commented Apr 14, 2023

I'm trying to test this with your docker image, and I'm not having any luck getting it to talk to my Redis server instance.

curl http://localhost:7379/SET/hello/world
curl http://localhost:7379/GET/hello

The commands above work as expected, but I'm not sure where this data is being written because my redis database is empty, even though I get a result back from webdis

I started it with the following command:

docker run -d --name Webdis --restart=unless-stopped -p 7379:7379 -v d:/redis-data/webdis/webdis.json:/etc/webdis.json nicolas/webdis

using the following webdis.json

{
    "redis_host": "redis-****.cloud.redislabs.com",
    "redis_port": 6379,
    "redis_auth": "****",
    "http_host": "0.0.0.0",
    "http_port": 7379,
    "threads": 5,
    "pool_size": 20,
    "daemonize": false,
    "log": "verbose",
    "websockets": false,
    "acl": [
        {
            "disabled": ["DEBUG", "FLUSHALL", "FLUSHDB"],
            "http_basic_auth": "*:*"
        }
    ]
}

Where is this data being stored, and how can I get it to talk with my specific instance?

@VagyokC4
Copy link
Author

I see now it's looking for webdis.prod.json, not webdis.json

@nicolasff
Copy link
Owner

I'm glad you figured it out. By the way, it does use webdis.prod.json because that's just what the command is set to in the Dockerfile, but you can certainly replace it when you run Webdis.

The docker run command you shared above uses the following mount:

-v d:/redis-data/webdis/webdis.json:/etc/webdis.json

This is the right way to inject the file, but you left the command (CMD) to its default value, which also means that it will start a Redis instance in the container – although it won't be used for anything. See here:

CMD /usr/bin/redis-server /etc/redis.conf && /usr/local/bin/webdis /etc/webdis.prod.json

To use your own config file, you just need to tell docker run what command to start the container with, after giving it the name of the image. In your case, you can keep the injected file as /etc/webdis.json and run Webdis with its path as a parameter, like this:

docker run -d --name Webdis --restart=unless-stopped -p 7379:7379 -v d:/redis-data/webdis/webdis.json:/etc/webdis.json nicolas/webdis /usr/local/bin/webdis /etc/webdis.json

I'll be adding a documentation page shortly that will provide detailed steps for how to run Webdis with an external Redis instance. This use case seems common enough that it's worth having a dedicated page for.

@VagyokC4
Copy link
Author

VagyokC4 commented Apr 17, 2023

I'm glad you figured it out. By the way, it does use webdis.prod.json because that's just what the command is set to in the Dockerfile, but you can certainly replace it when you run Webdis.

Yeah I was going in circles for a min. trying to figure out why I was reading/writing from Postman, but nothing appeared in my redis instance. Once I saw it was using .prod.json all became clear and worked as expected.

I'll be adding a documentation page shortly that will provide detailed steps for how to run Webdis with an external Redis instance. This use case seems common enough that it's worth having a dedicated page for.

Maybe make an image that is ONLY Webdis (webdis-server), without the redis bits? For my use case we will create Pods that run this image so the lighter the better.

I could see a webdis (what you have now), a webdis-stack which would embed the redis stack, and a webdis-server which is only webdis. The only other suggestion is to maybe go though and add the all new Redis commands so that manually adding them to the config is not necessary. Thoughts?

@nicolasff
Copy link
Owner

Maybe make an image that is ONLY Webdis (webdis-server), without the redis bits?

Yes, I've thought about it too. I'll look into it next time I prepare a release. My goal with the Docker images was really to make it as simple as possible to try out Webdis, but I realize that this isn't really the image you'd want to use if you're using Webdis within an existing architecture.

Another benefit of this is that while the images are already tiny (Docker Hub says 8.23 MB for the current latest) they would be even smaller without embedding Redis.

In the meantime I'll take a look at how other "connected" services build their images; by this I mean services/software that you would generally not run on its own but with the service connecting to other instances in the environment, instances it depends on. Docker Compose provides a reasonably simple way to do this, but I'm not sure whether it would be what Webdis users expect to use.

As for this point:

The only other suggestion is to maybe go though and add the all new Redis commands so that manually adding them to the config is not necessary.

I'm not sure what you mean here. By default Webdis disables the DEBUG command (because of the baffling existence of DEBUG SEGFAULT which was introduced before enable-debug-command).
The default acl config also provides an example of how to use basic auth for HTTP requests:

webdis/webdis.prod.json

Lines 15 to 24 in f4efbfd

"acl": [
{
"disabled": ["DEBUG"]
},
{
"http_basic_auth": "user:password",
"enabled": ["DEBUG"]
}
],

If you want all commands to be allowed, just remove any entry under acl that disables commands. This config lets you execute any command, for example:

"acl": [ ],

Disabling only DEBUG should not affect FT.<something> commands, they should be allowed. Now that enable-debug-command exists, "acl": [] might be a better default value to use.

There is also a wildcard "*" command to match all, if you want to create a super user for example. That said, the ACL feature in Webdis was added way back in 2011, when Redis didn't have an ACL command. These days it might be better to configure all this within Redis itself.

nicolasff added a commit that referenced this issue Apr 18, 2023
Inspired by the questions on issue #232. Documents what should be a
relatively common use case for Webdis users.
nicolasff added a commit that referenced this issue Apr 19, 2023
Inspired by the questions on issue #232. Documents what should be a
relatively common use case for Webdis users.
@VagyokC4
Copy link
Author

Yes, I stand corrected. The issues I faced were purely the bad configuration. I can confirm that no commands needed to be enabled in the configuration for it to work.

@nicolasff
Copy link
Owner

Cool, I'm glad it worked.

By the way, I've made some final tweaks to the docs page I mentioned on the other GitHub issue and pushed it. I've listed it first in the docs README since it feels like a common use case, with the title "Running Webdis in Docker with an external Redis instance".

This is not the first GitHub issue in recent months where a question eventually led to a docs page; I hope these can be useful. I still need to make the docs more prominent on the repo's main page, but first need to review the README to see if it might make sense to extract more of it there. In any case, thanks for bringing this up! It made Webdis better :-)

@VagyokC4
Copy link
Author

VagyokC4 commented Aug 1, 2023

Hi @nicolasff I was putting together a linqpad example for you and started running into some issues again.

using this config

{
    "redis_host": "localhost",
    "redis_port": 63791,
	"verbosity": 8,
	"logfile": "/dev/stdout",
    "http_host": "0.0.0.0",
    "http_port": 7379,
    "threads": 5,
    "pool_size": 20,
    "daemonize": false,
    "websockets": false,
    "acl": [
        {
            "disabled": ["DEBUG", "FLUSHALL", "FLUSHDB"],
            "http_basic_auth": "*:*"
        }
    ]
}

I'm using this image
docker run -d --name Redis-Stack-7-AOF -v c:/redis-data/:/data/ --restart=unless-stopped -e REDIS_ARGS="--save --appendonly yes" -e REDISEARCH_ARGS="MAXSEARCHRESULTS -1 MAXAGGREGATERESULTS -1 MAXDOCTABLESIZE 3000000 TIMEOUT 0" -p 63791:6379 redis/redis-stack-server:latest

which I can connect to externally, no problem
image

But webdis is giving me 503 service unavailable.
image

However, I can connect to other instances and it works no problem.

image

image

And I can change the docker command above to use the default redis port 6379 and it all works as well.

image
image

I have verbose on 8, yet I'm not seeing anything that would tell me what the problem is (while pointing to 63791).
Any ideas?

@VagyokC4 VagyokC4 reopened this Aug 1, 2023
@VagyokC4
Copy link
Author

VagyokC4 commented Aug 1, 2023

I'm wondering if the internal instance of Redis that webdis has is conflicting here.

I can confirm things work when I'm using a Redis not on my localhost. I can still reproduce the GET/POST issue, but my workaround seems to get me a result.

While using localhost instances, while I was able to PING the underlying redis, trying to execute some RedisStack commands give error
image

Which makes me think Webdis is pointing to it's internal instance even though from my outside host I can hit the redis stack instance using localhost:6379. I think this also explains why when I wire up to 63791, it cannot find a redis sitting there, because inside the docker instance it can't get to 63791.

Were you able to put together a -server image that does not include the internal Redis instance / internal network? That may help eliminate some of the not needed moving pieces.

@nicolasff
Copy link
Owner

Hey Charles, sorry I had missed this issue.

Which makes me think Webdis is pointing to it's internal instance even though from my outside host I can hit the redis stack instance using localhost:6379

localhost inside a Docker container is not the same host as on your computer. You can tell this by running Webdis with its default settings where it connects to Redis on localhost:6379, notice how this works even when you don't have Redis running on your machine. What does this tell us? That it connects to the embedded Redis and not the one on the host machine, since localhost in a container is a concept entirely limited to the scope of this container.

This is easy to validate, really. You can run Redis on your local machine and verify that it's listening on localhost:6379:

$ redis-cli -h localhost -p 6379 PING
PONG

and then install redis-cli in a simple container before trying the same command:

$ docker run --rm -ti alpine:3.18.3 /bin/sh
/ # apk add redis
fetch https://dl-cdn.alpinelinux.org/alpine/v3.18/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.18/community/x86_64/APKINDEX.tar.gz
(1/1) Installing redis (7.0.12-r0)
Executing redis-7.0.12-r0.pre-install
Executing redis-7.0.12-r0.post-install
Executing busybox-1.36.1-r2.trigger
OK: 10 MiB in 16 packages
/ # redis-cli -h localhost -p 6379 PING
Could not connect to Redis at localhost:6379: Connection refused

As expected, this fails since Redis is not running in this container (yes we've just installed it, but it's still not running).

So yes, if you tell Webdis to connect on localhost, it will connect to its embedded Redis.

What you are trying to do seems common enough that there's a Stack Overflow post about it with thousands of votes: "From inside of a Docker container, how do I connect to the localhost of the machine?".

As for this part:

Were you able to put together a -server image that does not include the internal Redis instance / internal network?

As I mentioned in the other issue, publishing images of Webdis takes quite a while. I have a list of steps I go through which currently has 33 steps, and signing all the different images requires a custom script that's over 450 lines long. This part requires entering 5 different passwords – most of them multiple times – to pass an API token to Docker Hub, to sign images with the Trust Key, the Root Key, the Repository Key, and then to auth with AWS to publish the images there.

You can read about the complex relation between images and various keys in the docs, described in detail by this diagram.

So no, I really can't do one-off releases when all it would take for you to test a custom image would be to edit the Dockerfile as you wish and then run docker build like this:

docker build -t webdis:custom .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants