-
Notifications
You must be signed in to change notification settings - Fork 44
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
Full docker support #123
Full docker support #123
Conversation
7d4c5f5
to
1d6a59a
Compare
I can't manage to use the build cache for the dependencies. I've created an issue in the cargo-chef repo to see if someone can help me to find the problem. |
UPDATE:
|
UPDATE: The permission problem was fixed using the I managed to deploy the container but the UDP port is closed. The API TCP port is working fine. I'm running the container with: docker run \
--publish 80:80/udp \
--publish 1212:1212 \
--volume torrustracker/test-volume:/app/storage \
registry.hub.docker.com/josecelano/torrust-tracker:0.4.0 The volume has the proper configuration file (./storage/config/config.toml). I've opened an issue on the docker forum: https://forums.docker.com/t/unable-to-open-a-udp-port-on-port-80/132661. You could not expose more than one port some years ago, but now you can also do it with the Azure dashboard assistant. I do not see any error running the container so I guess it's a firewall/forwarding issue. |
UPDATE: Problem 1: closed portI've spent the whole day trying to find out why the UDP tracker does not work. I was using this service to check if the port is open. The service says the port is closed, but in fact, I can connect using netcat: $ nc -u 20.246.181.9 6969
ss
bad request In the end, there was no problem exposing the UDP port on the Azure container. Problem 2: qBittorrent can't connectAfter confirming that the port was responding, I thought the client could be the problem. I'm using BitTorrent v4.4.1. After trying different combinations on the server and client sides, this one worked: Tracker URL on the client: Tracker config on the server: log_level = "debug"
mode = "public"
db_driver = "Sqlite3"
db_path = "./storage/database/data.db"
announce_interval = 120
min_announce_interval = 120
max_peer_timeout = 900
on_reverse_proxy = false
external_ip = "0.0.0.0"
tracker_usage_statistics = true
persistent_torrent_completed_stat = true
inactive_peer_cleanup_interval = 600
remove_peerless_torrents = false
[[udp_trackers]]
enabled = true
bind_address = "0.0.0.0:6969"
[[http_trackers]]
enabled = true
bind_address = "0.0.0.0:6969"
ssl_enabled = false
ssl_cert_path = ""
ssl_key_path = ""
[http_api]
enabled = true
bind_address = "0.0.0.0:1212"
[http_api.access_tokens]
admin = "MyAccessToken" I do not know why it's working now because I tried that configuration since the beginning. I remember that @Power2All reported a problem with qBitTorrent before. Problem 3: UDP debug messages do not appear in logsThere is a problem that made me think the UDP tracker was not receiving the request. With debug enabled It does not show these two messages: debug!("Received {} bytes from {}", payload.len(), remote_addr);
debug!("{:?}", payload); It happens when I run the tracker with docker on both my local machine and the Azure container. But It does not happen when you run the app directly on your machine with I can see messages from the parent thread (main docker process) and the first child: $ docker logs heuristic-stonebraker
2022-12-09T14:34:15.173329600+00:00 [torrust_tracker::logging][INFO] logging initialized.
2022-12-09T14:34:15.193516700+00:00 [torrust_tracker::jobs::udp_tracker][INFO] Starting UDP 197789626+00:00 [torrust_tracker::jobs::torrent_cleanup][INFO] Cleaning up torrents.. But the primary process uses Problem 4: every time I restart the Azure container, the IP changesI have to find a way to assign a static IP for the time being. Maybe this could be the solution. Later, when I start using Nginx and docker-compose I want to use a domain instead. |
UPDATE: Regarding problem 3, I've found the problem. In the
The |
Azure Container Instances (ACI) do not allow to mount a single file. There is no support for mounting a single file, or mounting a subfolder from an Azure File Share. More info: https://docs.docker.com/cloud/aci-container-features/#persistent-volumes Due to that I had to move both files (data.db and config.toml) to a folder. THis way we can run the container with: ``` docker run -it \ -p 6969:6969 -p 1212:1212 \ --volume "$(pwd)/storage":"/app/storage" \ josecelano/torrust-tracker ``` BREAKING CHANGE: `config.toml` file was moved to `./storage/config/`.
Azure file share volume mount requires the Linux container run as root. https://learn.microsoft.com/en-us/azure/container-instances/container-instances-volume-azure-files#limitations
I think that could be the reason why the application does not work on the Azure Container Instance.
The Cargo.toml file has these options: ``` [profile.release] debug = 1 opt-level = 3 lto = "fat" strip = true ``` I think that hides "debug" messages in release builds. SO when I use the docker image on Azure container or my local machine I do not see those messages. I think for the time being we can show them. On the other hand, there is a "debug" message that should be an "error" message: ``` Err(_) => { error!("could not write response to bytes."); } ``` That message shoudl be shown on production too.
The problem with the cargo dependencies cache in docker is the option `strip` in the release profile: ``` [profile.release] debug = 1 opt-level = 3 lto = "fat" strip = true ``` Removing the option `strip = true` fixes the problem as described here: LukeMathWalker/cargo-chef#172
I'm trying to publish the port 6969 for both TCP and udp and I get this error: $ docker run \
--publish 6969:6969/udp \
--publish 6969:6969/tcp \
--publish 1212:1212/tcp \
--volume torrustracker/test-volume:/app/storage \
registry.hub.docker.com/josecelano/torrust-tracker:0.7.0
[+] Running 0/1
⠿ Group sweet-gates Error 4.2s
containerinstance.ContainerGroupsClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="DuplicateContainerPorts" Message="Duplicate ports '6969' found in container group 'sweet-gates' container 'sweet-gates'." It's working with docker on my machine, so It must be an Azure constrain. |
On Azure Container Intances we are getting an error if we tried to publish a port wiht both DP and TCP. The error: ``` containerinstance.ContainerGroupsClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="DuplicateContainerPorts" Message="Duplicate ports '6969' found in container group 'sweet-gates' container 'sweet-gates'." ```
User in production and development docker images is different.
UPDATE: Added docker-compose configuration for development. You can run it with |
UDPATE: hi @WarmBeer @da2ce7, I've been able to deploy the Tracker to Azure Container Instances with docker compose, but only with one service (the tracker). When I try to add other services like Nginx, Certbot, and Mysql, the instance gets stuck in "creating" or "updating" state. I've created a new repo with all the configurations I've been testing: https://github.com/josecelano/awesome-torrust-tracker-compose. I think the reason is Azure Container Instances are very small, you only have 4 CPUs for all the containers. They even recommend using Azure Container Apps when you have more complex services. I prefer K8S than Azure Container Apps because you could use it with the other big cloud providers. I'm going to add to this PR the docker-compose configuration to run all those services locally. It works locally when I use Nginx and MySQL. I think we can keep a sample config in this repo with Nginx (reverse proxy) and MySQL, but without certbot. I can add another example to the new repo for deploying the app with docker-compose to another provider. For example, Digial Ocean with a droplet or K8S. |
It seems you can create remote contexts with your docker nodes (virtual machines with docker): docker context create remote --docker "host=ssh://[email protected]"
docker context ls
# output:
default * .... unix://var/run/docker.sock .... swarm
remote .... ssh://[email protected] I think this is better than ACI (for our requirements) because
The example sets up the Nginx and Certbot on the docker host (VM) instead of using docker-compose. I think I would keep that configuration in the docker-compose, even if we need an extra Nxing instance on the host as load balancer (or gateway). My idea was even more straightforward: just to run "docker-compose" manually on the VM. The advantage of the previous solution is you can deploy or update remotely, for example, from a CI workflows. |
I tried to deploy the tracker to Digital Ocean App Platfom, but it's not possible for two reasons:
It would be very easy to deploy if we could inject the configuration using env vars (and use MySQL instead of SQLite). @da2ce7 since you are working on the setting overhaul, I think you should consider that env vars for configuration is still a common way to inject configuration variables. With Kubernetes, you can mount a file with secrets. It seems that's a safer way to do it. In that case, we should be able to generate a K8S secret file from the tracker configuration. See https://kubernetes.io/docs/tasks/configmap-secret/managing-secret-using-config-file/. I think we should make it clear which config values are secrets and which are not. In general, I've always seen people using the same list, for example, the common |
@josecelano I would suggest you check out the Docker deployment on my Axum project. It doesn't need any "volumes" and such, and might be what you're looking for. It uses also ENVIRONMENT variables to be used to build for instance the configuration file, so that it can be deployed anywhere. |
hey @Power2All thank you! I've already done it before starting to work on the PR. I think you did a great job. You are generating the On the other hand, the config.toml file allows you to define the configuration for multiple udp_trackers and http_trackers which is not supported by your solution right now. Anyway, today @WarmBeer @da2ce7 and I were discussing how to handle the application configuration. It was a long discussion, but to make it short, we agree that that should be definitively a feature and not a hack for deployments. I mean, we should change the application to accept env vars for the configuration because that's a common practice in a lot of hosting providers. One of our ideas, the want we agreed on at the end, was we could add a new env var (for example We discussed a lot of ideas. Maybe we should open a discussion for it. @da2ce7 is working on a refactoring of the configuration which is related to this. And I also proposed a new feature to generate the configuration file. |
Correct, I was planning to fix that up as well, but had no time to look into that. |
I've extracted part of this PR into a new PR. It's the HTTPS support for the API. |
I've created a new PR to replace this one. |
6851ec5 fix: docker image run as non root (Jose Celano) 171a37d feat: publish docker image for tags, develop aand main branches (Jose Celano) 032f6a6 fix: docker repo name in README (Jose Celano) 46e1a37 feat: docker support (Jose Celano) f8700aa feat: allow to inject configuration from env var (Jose Celano) 3098ed2 feat: remove strip from Cargo.toml (Jose Celano) 269e5f5 feat: move default db_path to storage folder (Jose Celano) ca0e8af feat: change default http tracker port to 7070 (Jose Celano) b1ec9df feat: change udp tracker console output (Jose Celano) 19abf0f fix: error when udp response can't be written (Jose Celano) b23d64b feat: add ssl support for the API (Jose Celano) 5af28a2 fix: the pedantic clippy warnings (Jose Celano) Pull request description: Stacked on/Depends on: #128 This is a reorganization of [PR-123](#123) - I've reorganised the commits - I've implemented [Solution 1](#127 (comment)) discussed [here](#127 (comment)). The application can get the configuration from the `config.toml` file or from an env var `TORRUST_TRACKER_CONFIG` with the same content as the `config.toml` file. I think it's the minimum change to deploy the application using docker easily. The idea is the same as the solution implemented by @Power2All [here](https://github.com/Power2All/torrust-axum/tree/master/docker). But I'm using only one env var. This way, we do not need to change the code if the configuration changes. On the other hand, we are discussing a new implementation for the [settings](#127), and I did not want to implement things that will need to be changed afterwards. I'm also a fan of small steps :-). ## Testing I have deployed the application to the Digital Ocean App Platform: https://lobster-app-dc6o9.ondigitalocean.app/api/stats?token=MyAccessToken with [this PR branch docker image](https://hub.docker.com/layers/josecelano/torrust-tracker/docker-reorganized-pr/images/sha256-d08ccf6183c451910ba3dfb74695108700b1aaa2dd13f85bf6f0bdecc4bf43d9?context=repo). If you want to test the feature of getting the configuration from an env var locally (without docker): ```s TORRUST_TRACKER_CONFIG=`cat config.toml` cargo run ``` With docker, you only need to follow the instructions in the README: ## Notes Digital Ocean App Platform only allows you to expose one port (0.0.0.0:8080). I've deployed it exposing only the API with this configuration: ```toml log_level = "info" mode = "public" db_driver = "Sqlite3" db_path = "data.db" announce_interval = 120 min_announce_interval = 120 max_peer_timeout = 900 on_reverse_proxy = false external_ip = "0.0.0.0" tracker_usage_statistics = true persistent_torrent_completed_stat = false inactive_peer_cleanup_interval = 600 remove_peerless_torrents = true [[udp_trackers]] enabled = false bind_address = "0.0.0.0:6969" [[http_trackers]] enabled = false bind_address = "0.0.0.0:7070" ssl_enabled = false ssl_cert_path = "" ssl_key_path = "" [http_api] enabled = true bind_address = "0.0.0.0:8080" ssl_enabled = false ssl_cert_path = "" ssl_key_path = "" [http_api.access_tokens] admin = "MyAccessToken" ``` I suppose you need to create three apps sharing the state with a MySQL service if you want to deploy all the services. You want to do the same if you want to deploy more than one UDP or HTTP tracker. ACKs for top commit: josecelano: ACK 6851ec5 da2ce7: ACK 6851ec5 Tree-SHA512: 47a6c6d1240986f65f02fafc3ddce32cb4fc50bc118f833cdf7fd67afdef5b3dd42fbd8d46a22df818966b14b3fb3d0b1ab971a28dbec9c271b872b7c966276f
This is a re-work of PR-55 adding more features.
UPDATE ON: 2022/12/16
TASKS
storage/database
dir.SUBTASKS (deploy with docker)
This option is a deployment to ACI using only one container with SQLite and no HTTPS.
SUBTASKS (deploy with docker-compose)
certbot
. DISCARDED for this PR.REQUIREMENTS
root
user.OPTIONAL
.devcontainer
configuration for GitHub Codespaces. DISCARDED for this PR.LINKS