Many people have problems for setting connectivity between containers, home private network and Internet on Synology NAS. There’re few different points than normal linux systems such as Synology NAS has no built-in docker-compose
program and it has the tricky firewall.
Below will use them as example:
postgresql
A and express.js
B from official on dockerhubDSM 6.2.4-25556 Update 6
A
recordLet's encrypt
Important things at this section are exposing ports of containers. Docker image of postgresql
exposes port 5432 default, and it needs some environment variables for setting. If you want to know more about them, please refer section of environment variables on Docker Hub. In description of this article, express.js
is considered as exposing port 4000 at codebase.
Because base image of node and postgres already expose port, I just use technique of multi-stage packaging about docker.
FROM node:XX.XX.X-alpineX.XX AS builder
ARG NODE_ENV=production
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --legacy-peer-deps
# The instructions for second stage
FROM node:XX.XX.X-alpineX.XX
WORKDIR /usr/src/app
COPY --from=builder /usr/src/app/node_modules node_modules/
COPY . .
CMD [ "npm", "run", "start:prod" ]
I’m inspired and it should be credited to article of Alex Barashkov on dev.to: Using Docker for Node.js in Development and Production. This article shares benefit about short-time of re-packaging an image if there are only new features or bug-fixing be added to codebase and no new version of packages are introduced.
npm run start:prod
should accompany with scripts in package.json
file. Below are exerpted content of package.json
.
// package.json
"scripts": {
"start:prod": "NODE_ENV=production node src/server.js",
},
It should be set two rules in synology firewall in order. First rule is allowing
source IP are 192.168.1.0/24
and they can
reach all ports. Second rule is denying
source IP range from all IPs
and cannot
reach all ports.
Remind: Control panel has firewall for setting.
You must create an user-defined bridge network on Docker program because default bridge network has no DNS capability between docker containers. That’s mean containers cannot communicate with / connect to others' via containers' names.
demo_network
as an example.
Here I let docker image postgresql
be container A and image express-server
be container B. Container A uses port 5432
in user-defined bridge network. Container B uses port 4000
in user-defined bridge network and exposes port 40000
in home private network.
You can setup container by clicking launch button at images tab.
Steps:
Steps:
Do you remember what ip range we assumed above for the user-defined network: demo_network
? You need the ip range here and I assume you use same range mentioned above. Because in this example I just create two containers and first IP is reserved for gateway of the user-defined network whose has no extra or special setting, IPs of two containers, which are postgres(container A) and express-server(container B), are 172.17.0.2
and 172.17.0.3
respectively. I also let their ports on the user-defined network are 5432
and 4000
.
Please add new rule for source from 172.17.0.0
and subnet mask 255.255.0.0.
to firewall. This new rule is allowing to access ports of 5432
and 4000
.
Let’s assume your home private network is 192.168.1.0/24
. Is it similar with NAS its network? Yes, that’s right, the NAS server is within home private network and be a node of them. Here I create new rule to firewall for allowing traffic as source IP is 172.17.0.3
can access port 40000
using TCP. This rule and its order lets container B can respond to any incoming requests. Combining it with one fundamental rule for 192.168.1.0/24
, container B can interact with any request from home private network.
After finishing above, containers can communicate each other and can be connected within private network using private IP.
If I create new rule to firewall for allowing requests coming from Internet to access and also setup reverse proxy, container B can be accessed right? Yeah, you’re right. I will describe steps in next section.
Steps:
Synology NAS has reverse proxy server service, you can use it. Its path is Control panel
-> Application portal
-> Reverse Proxy
.
Create a record of reverse proxy server for container B and some domain name you want to mapping. After clicking create button at reverse proxy tab, you can type information of domain name and container B to the shown dialog. At general tab, you can:
HTTPS
protocol, port 443
and I recommend you mark checked two options: Enable HSTS
and Enable HTTP/2
.HTTP
protocol, a NAS private IP(192.168.1.x, an ip NAS is using now) as hostname and container exposed port. For example here, port 40000
is the one of container B exposed to home private network. Here I use test.xxxxxx.cc
as an example domain name.Notice: Please make sure the domain name you actually own or on your rent period.
You can use your own ssl certificate. If you don’t have one, you should prepare formal one before doing this section. If you want to try free ssl certificates, I recommend you to try let's encrypt
via acme.sh
on synology NAS.
Steps:
Control panel
-> Security
-> Certificates
-> click Configure
button*.xxxxxx.cc
and it lets any sub domain name can use itself for https
.
Create new firewall rule for allowing traffic from Internet to https reverse proxy service port 443
. Just create new one as following one picture does.
It’s final part about connectivity and it’s so important for every request coming from Internet can use domain name to connect. Without this DNS setting, all Internet requests can only use IP to communicate to your NAS server. Here I use Cloudflare DNS setting as example, you can follow similar steps in any DNS service provider.
A
record.A
record.
Thanks my friend icemango for kindly reminding me using command docker inspect
to examine network connectivity between containers. So that I can investigate from little things to larger range. Initially, I was thought all problem comeing from the packages within docker images are too new and incompatible with latest node version(version 18 series
). Actually, it’s part of unworkable reasons. After I downgrade environment version to be known as workable, express-server
container still cannot connect to the other one. So I start to trouble-shoot network connectivity from little granularity to larger one.