-
Notifications
You must be signed in to change notification settings - Fork 40
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
Docker Support #11
Comments
I built my own Docker image just to keep it more organized when running, but I ran into the issue that Torrust can't get the correct client IPs while inside Docker. There's a relevant issue here discussing the problem and some potential solutions, like giving the container host network access. |
I'm planning on adding Docker images, after I add support for reverse proxy's 😄 |
I'll happily package this for Kubernetes once Docker support is done, as a bonus. |
I've created a PR with a Dockerfile only for this service. We could create docker images also for the backend and frontend. I think it would be also helpful to create a docker-compose file in order to build and run all the services with a single command. That it would make much easier to start coding and also it would make it easier for other developers to try things without having to install all the dependencies. The docker-compose configuration could be located in a new repo. The other option could be generate docker-compose file only for the torrust-index. So when you start working you need to run two commands. Right now developers are likely to work on all the projects at the same time but I suppose as the project became bigger you probably are not going to work on both the tracker and the index at the same time. In conclusion, one docker-compose file for the torrust-index could be a good option and we can add it to the torrust-index repo. |
Hi @josecelano - take a look at https://github.com/zorlin/torrust-docker ... :) |
Hi @Zorlin cool!!! Just a couple of questions/comments:
I'm going to follow your instructions to run it on my laptop and I will give you feedback. |
@josecelano https://github.com/Power2All/torrust-axum/blob/master/docker/Dockerfile Use it however you like though, it's suppose to be used in combination with either a direct host connection, or could be used in combination with Traefik/NGINX for instance. It's not perfect, but it works pretty good. |
Thank you, @Power2All I've been looking at it. I'm working on this PR. I have defined some requirements on the PR. Feedback for the requirements is welcome. I have not added an explicit goal for the PR, but mainly I want to:
I see you have also added SSL support for the API. |
No problem, been busy with a new job I just started at, so I've not been around much to work on the code lately anyhow. Good thing the project is still moving :)
Correct, wasn't really that hard though. |
hi @PseudoResonance could you elaborate on this? how can I reproduce that problem? I've been running the tracker with docker locally and on an Azure Container Instance with the standard configuration and without using a reverse proxy but I have tested only the UDP tracker and the API. |
Probably need to use X-Forwarded-For and UDP doesn't know origin connecting client. This needs to be looked into. |
It's been quite a long time, but I believe if you setup a docker container and only open the port, Docker's networking will end up masking the IP, as Power2All said. The easiest solution being to simply bypass Docker and use host networking, and another solution being to use a reverse proxy to set X-Forwarded-For before the network traffic reaches Docker. |
Hi, I've been testing the docker container. I have deployed the tracker to a droplet following this article by @mrdaniel. I was able to set up the three services:
I've explained all the details here. For the API and the HTTP tracker, I'm using Nginx as a reverse proxy (with certbot). I could not set up a reverse proxy for the UDP tracker, but you can access the docker port because, by default, it bypasses the firewall rules. Regarding IP and Ports, I would like to understand all the available settings. I think you can have all the scenarios described below (is it OK @WarmBeer?): HTTP API
HTTP Tracker
Settings: It uses two options:
The peer address IP is calculated in two places:
The /// GET /announce or /announce/<key>
fn announce(tracker: Arc<tracker::Tracker>) -> impl Filter<Extract = impl warp::Reply, Error = Rejection> + Clone {
warp::path::path("announce")
.and(warp::filters::method::get())
.and(with_announce_request(tracker.config.on_reverse_proxy))
.and(with_auth_key())
.and(with_tracker(tracker))
.and_then(handle_announce)
} If The handler: pub async fn handle_announce(
announce_request: request::Announce,
auth_key: Option<auth::Key>,
tracker: Arc<tracker::Tracker>,
) -> WebResult<impl Reply> {
// ...
let peer = peer::Peer::from_http_announce_request(&announce_request, announce_request.peer_addr, tracker.config.get_ext_ip());
let torrent_stats = tracker
.update_torrent_with_peer_and_get_stats(&announce_request.info_hash, &peer)
.await; The UDP TrackerThe UDP tracker only calculates the peer IP while handling the request. There is no HTTP header. Notes/Questions:
Extra infoI do not know how the docker network mode "host" relates to this issue and potential problems using the tracker with docker. To make it clear, there are two problems:
Example response from the API with the peer for the URL: https://tracker-api.josecelano.site/api/torrent/0b3aea4adc213ce32295be85d3883a63bca25446?token=*** {
"info_hash": "0b3aea4adc213ce32295be85d3883a63bca25446",
"seeders": 1,
"completed": 0,
"leechers": 0,
"peers": [
{
"peer_id": {
"id": "2d5452333030302d726a7339376b753078346273",
"client": "Transmission"
},
"peer_addr": "YOUR_PUBLIC_IP:51413",
"updated": 1671465070905,
"updated_milliseconds_ago": 1671465070905,
"uploaded": 0,
"downloaded": 0,
"left": 0,
"event": "Started"
}
]
} ConclusionsRegarding docker configuration, I suppose you can run the tracker with docker with the limitation of exposing the UDP port directly. But I suppose that is not a docker problem but a proxy limitation. Any suggestions or comments? I would like to merge the docker support #129 PR if it has no problems. |
@josecelano This might be interesting reading: |
Exposing the UDP tracker directlyIn my case, it works with docker-compose when I expose the docker port using a wildcard socket ( $ docker network ls
NETWORK ID NAME DRIVER SCOPE
88c881bc7a28 droplet-docker-context_server_side bridge local $ docker network inspect 88c881bc7a28
[
{
"Name": "droplet-docker-context_server_side",
"Id": "88c881bc7a283b4f092cda1d38b8a5d308c010cd7eb8ae2bdba31572497e76fe",
"Created": "2022-12-20T09:29:27.419222891Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.21.0.0/16",
"Gateway": "172.21.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"7b1b83242f0251c0a1c750e8ca1e11da3375e959abf3d6f5a0022675724130ad": {
"Name": "droplet-docker-context-mysql-1",
"EndpointID": "fc59a0ea0e75842f0b01bce64ab4e1342dcb22c50f500887c7976e21b2e849f3",
"MacAddress": "02:42:ac:15:00:02",
"IPv4Address": "172.21.0.2/16",
"IPv6Address": ""
},
"e9ef561bd4f00aff2d32ab369f69c7f869e7c6df6d7df14734137e3dae7ecdb0": {
"Name": "droplet-docker-context-tracker-1",
"EndpointID": "4266c74316affc996559c2ded6ee4daa138d0be4a732a0de9b4a5a8ca4b04fc9",
"MacAddress": "02:42:ac:15:00:03",
"IPv4Address": "172.21.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "server_side",
"com.docker.compose.project": "droplet-docker-context",
"com.docker.compose.version": "2.13.0"
}
}
] $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e9ef561bd4f0 josecelano/torrust-tracker:docker-reorganized-pr "/app/torrust-tracker" 6 hours ago Up 6 hours 0.0.0.0:1212->1212/tcp, :::1212->1212/tcp, 0.0.0.0:7070->7070/tcp, :::7070->7070/tcp, 0.0.0.0:6969->6969/udp, :::6969->6969/udp droplet-docker-context-tracker-1
7b1b83242f02 mysql:8.0 "docker-entrypoint.s…" 7 hours ago Up About a minute (health: starting) 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp From docker docs: Note that ports which are not bound to the host (i.e., -p 80:80 instead of -p 127.0.0.1:80:80) will be accessible from the outside. This also applies if you configured UFW to block this specific port, as Docker manages its own iptables rules I read in this article that you should bind UDP services to a specific IP address because the system does not know where you like to source the packet from. I did an experiment with the tracker and with another sample application which is a UDP echo server. Instead of binding to the wildcard socket ( services:
echo-udp:
build:
context: .
ports:
- 8080:8080/udp
networks:
app_net:
ipv4_address: 172.16.239.10
command: "172.16.239.10:8080"
networks:
app_net:
name: upd_echo_net
ipam:
driver: default
config:
- subnet: "172.16.239.0/24" I tested both options, and It works. You can test it:
You should see:
You can open a new terminal and execute: nc -u 127.0.0.1 8080 If you type something, will see the output on the previous tab: droplet-echo-udp-context-echo-udp-1 | Echoed 6/6 bytes to 172.16.239.1:35368 It also works with the container IP Exposing the UDP tracker behind an Nginx reverse ProxyI could not set up the Nginx as a reverse proxy for the UDP tracker. This is not a problem with the docker configuration. I suppose the Nging configuration is wrong. I'm using this configuration:
The Nginx and the "udp echo" container are listening:
I can connect to the container remotely (using the server's public IP) but not to the Nginx. I also tried to bind the container socket to the container IP, but it did not work. I tried with and without the option:
As described here that _"enables the upstream server to observe the full source IP address, so it can construct response datagrams that are sent directly to the remote client. The upstream server generates response (“egress”) packets with the correct IP destination, but using its local IP address as the source address. The source address needs to be rewritten to the IP address and port of the NGINX Plus load balancer that the client originally connected to."_ It seems that with that option, the tracker container or the echo UDP container should be able to send the response directly to my public IP (on my local machine). But I do not receive any response. $ sudo netstat -tulpn | grep :8181
udp 0 0 0.0.0.0:8181 0.0.0.0:* 9871/nginx: master deployer@josecelano-torrust-tracker:~$ sudo netstat -tulpn | grep :8080
udp 0 0 0.0.0.0:8080 0.0.0.0:* 9607/docker-proxy
udp6 0 0 :::8080 :::* The docker processes:
Anyway, I think this problem is out of the scope of this issue. The UDP tracker works fine with docker. |
@josecelano Nice, thanks for also jumping into it :) |
Is Docker support planned? A docker container for the tracker and backend/frontend would be amazing.
https://blog.logrocket.com/packaging-a-rust-web-service-using-docker/
The text was updated successfully, but these errors were encountered: