How to migrate VM with exposed ports to docker?

I have an Ubutnu VM (created on 12.0 which I still use now on 24.10.2.2) to host NGINX and Prosody. The other day I decided to try WireGuard and installed my first app “wg-easy” to familiarize myself with it before attempting to install it on the VM. But because of the easy install, volumes, and low RAM usage, I’m contemplating migrating my whole VM to docker instead.

This seemed impossible at first but after some thought I think all I need to do is copy /etc/letsencrypt/ from the VM to a dataset, use the official certbot image and bind mount this directory to its container and also NGINX and Prosody. As for NGINX I’m guessing I also need to replace localhost with a docker internal IP, e.g. proxy_pass localhost:5280 to 172.16.1.2:5280.

Is that a reasonable procedure? I don’t know the best practices when it comes to containers, I’m using a VM because it’s the “easy way”. But now I realize that I should not treat my VM as a pet (configuring users, SSH, rsync, updates etc.), with docker I simply SSH into Truenas. However… my biggest concern is security/isolation. The VM has a separate IP (192.168.1.3) and from the router I port forward 80,443,5222,3478 to it; whereas with docker I instead specify the IP of my NAS (192.168.1.2). So if a vulnerability where to be found, (AFAIK) an attacker will have root access to my NAS instead of user access on my VM. I also read that neither Truenas nor containers have a firewall. The VM has policy DROP along with some simple rules to allow only minimum IN/OUT packets (e.g. iptables -A OUTPUT -p tcp -m multiport --sports 80,443,5222,3478 -j ACCEPT). Docker documentation states to use iptables -I DOCKER-USER, but I’d rather not mess with the CLI and stick to what’s supported.

How should I properly approach this? Any help/advice is appreciated!

Regarding the LE: you can just try to do so. However, IMO, it’s better to make the container issue the cert by itself and not mess with existing certs. You can consider swag, for one.

Also, usually there is some kind of separation between services – each in its own container. I think it’s a good idea to have two containers – one for reverse proxy and one for Prosody.


Regarding the proxy_pass: you can use something like proxy_pass <prosody_container_name>:5280 as long as both containers are connected to the same (docker) network.


Port forwarding would lead to the container (as it was in the VM case). So, unless your container has root privileges, an attacker wouldn’t automatically get access to your NAS.

(I’m not familiar with IPs for containers stuff, so) in case your containers have the same IP as the host, you wouldn’t be able to use port 443 and/or 80. You would need to map these ports for some different values.


I’m not familiar with the firewalls, so no comments on this one.