Managing different applications from different domains on the same host can be difficult when using different ports. When a colleague suggested I write an article about using Podman to solve that problem, possibly using a reverse proxy, I jumped at the chance.
[ Download now: Podman basics cheat sheet ]
I recently wrote an article about configuring a container to start automatically as a systemd service, which expanded on an idea from my previous article about creating fast, easy, repeatable containers with Podman and shell scripts. Thanks to my colleague Jason, I'm expanding on another idea: In this article, I will explain how to use Podman and Nginx to work with applications from different domains on the same host.
Basic assumptions
Why is there a need for a reverse proxy for this proposed scenario? Because of Podman's inherent way of working. To clarify, consider the following scenario.
In a traditional environment, to run a given web application, you'd probably set aside a dedicated server configured with all the necessary web tools for that application. That application would be given a fully qualified domain name (FQDN) which would, in turn, respond to a specific DNS server and domain server. To have a second or third application answering to different DNS and domain servers, you'd probably do the same steps with servers dedicated to each application. I don't need to say how laborious, tiring, tedious, and impractical this is.
Now that you're navigating the ocean of containers, you know you can do the same thing using just a single host and multiple containers running on different high ports on that same host. This is a wonderful solution for most of your infrastructure problems. But now you have a new dilemma: Each new container you run in a different domain uses a different port on your host to communicate with the outside world, so you must manage several different ports for each application. Now you're back in that same tiresome place you started.
You know there are several solutions proposing to solve precisely this type of problem, the so-called reverse proxies. But how can you make it work with Podman and its various containers inside your host? This article will answer that question!
I'll illustrate how to use Nginx to make applications responding on different domains all use the same port on your host to communicate with the outside world. For brevity's sake, I'll omit certain basic configuration steps, but not the main ones.
[ Get hands on with Podman in this tutorial scenario. ]
Configuring and deploying your web applications with Podman
Start by pulling the needed container images for this configuration:
$ podman pull docker.io/library/httpd
$ podman pull docker.io/library/nginx
$ podman image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
..output omitted…
docker.io/library/nginx latest 3f8a00f137a0 2 weeks ago 146 MB
docker.io/library/httpd latest 3a4ea134cf8e 2 weeks ago 150 MB
Then create two different directories to host your web app data. In this case, I'll work with two simple HTTPD webpages:
$ mkdir syscom sysorg
$ ls -l
total 32
...output ommited...
drwxr-xr-x. 2 localuser localuser 6 fev 27 17:08 syscom
drwxr-xr-x. 2 localuser localuser 6 fev 27 17:08 sysorg
I'll create two index.html files, one for the sysadmin.com app and the other for the sysadmin.org app:
$ cat << EOF > ./syscom/index.html
<html>
<header>
<title>SysAdmin.com</title>
</header>
<body>
<p>This is the SysAdmin website hosted on the .com domain</p>
</body>
</html>
EOF
$ cat << EOF > ./sysorg/index.html
<html>
<header>
<title>SysAdmin.org</title>
</header>
<body>
<p>This is the SysAdmin website hosted on the .org domain</p>
</body>
</html>
EOF
This is all I need. Now I can run my HTTPD containers hosting these two different webpages in different domains:
$ podman run --name=syscom -p 8080:80 -v $HOME/syscom:/usr/local/apache2/htdocs:Z -d docker.io/library/httpd
4b4c00f0faa5c6cbc5a8d21d91ac5b4dbb25b1024db8477de313824bc1775db3
$ podman run --name=sysorg -p 8081:80 -v $HOME/sysorg:/usr/local/apache2/htdocs:Z -d docker.io/library/httpd
ff1d8bae380ab9b57418b09b77b875cff5d52ee58707ea1f100a6bea40156154
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4b4c00f0faa5 docker.io/library/httpd:latest httpd-foreground 15 seconds ago Up 14 seconds 0.0.0.0:8080->80/tcp syscom
ff1d8bae380a docker.io/library/httpd:latest httpd-foreground 9 seconds ago Up 8 seconds 0.0.0.0:8081->80/tcp sysorg
Keep in mind that I'm not going into the details of DNS and domain configuration externally, but for ease of demonstration, I've included these FQDNs in my /etc/hosts file specifying the same IP for both.
Note that if I try to access both through the default port 80, neither of them responds since, by default, the operating system security policies for Podman allow me to configure only high-access ports for these applications, so the sysadmin.com application responds on port 8080 while the sysadmin.org application responds on port 8081 from the same host:
$ curl http://sysadmin.com
curl: (7) Failed to connect to sysadmin.com port 80 after 1 ms: Connection refused
$ curl http://sysadmin.com:8080
<html>
<header>
<title>SysAdmin.com</title>
</header>
<body>
<p>This is the SysAdmin website hosted on the .com domain</p>
</body>
</html>
$ curl http://sysadmin.org
curl: (7) Failed to connect to sysadmin.org port 80 after 0 ms: Connection refused
$ curl http://sysadmin.org:8081
<html>
<header>
<title>SysAdmin.org</title>
</header>
<body>
<p>This is the SysAdmin website hosted on the .org domain</p>
</body>
</html>
Now the reverse proxy magic with Nginx begins!
[ Learning path: Getting started with Red Hat OpenShift Service on AWS (ROSA) ]
Reverse proxying your apps to the same port with Nginx
First, create a directory to contain all your configuration files for Nginx and enter it:
$ mkdir nginx
$ cd nginx/
Inside this directory, create three different files:
- The
default.conffile, which holds the default Nginx configuration - The
syscom.conffile, which holds the configuration for the sysadmin.com application - The
sysorg.conffile, which holds the configuration for the sysadmin.org application
For each domain, use server_name to define the domain and proxy_pass to map the container, also specifying the IP address of the host machine and the mapped port for each container. Now all of them are going to listen on the 80 port using your reverse proxy as a gateway:
$ cat << EOF > default.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
EOF
$ cat << EOF > syscom.conf
server {
listen 80;
server_name sysadmin.com;
location / {
proxy_pass http://192.168.1.30:8080;
}
}
EOF
$ cat << EOF > sysorg.conf
server {
listen 80;
server_name sysadmin.org;
location / {
proxy_pass http://192.168.1.30:8081;
}
}
EOF
Making this work requires taking advantage of the include /etc/nginx/conf.d/*.conf parameter of the /etc/nginx/nginx.conf file inside the Nginx container, which allows loading modular configuration files inside from the /etc/nginx/conf.d/ directory. When it runs, these files will be mounted in this directory inside the container.
Now it's time to run the Nginx container with the proper parameters. The first time you run it, however, especially running rootless containers, you may receive the following error message:
$ podman run --name=nginx -p 80:80 -v $HOME/nginx:/etc/nginx/conf.d:Z -d docker.io/library/nginx
Error: rootlessport cannot expose privileged port 80, you can add 'net.ipv4.ip_unprivileged_port_start=80' to /etc/sysctl.conf (currently 1024), or choose a larger port number (>= 1024): listen tcp 0.0.0.0:80: bind: permission denied
This is a standard and expected security measure. To work around this and allow the Nginx container to run using the low port 80 at runtime, run:
$ sudo sysctl net.ipv4.ip_unprivileged_port_start=80
net.ipv4.ip_unprivileged_port_start = 80
Siren alert: Proceed with this setting cautiously, as it could create a vulnerability. After the container runs, you can return this setting to the default value of 1024.
Now run the container again and see what happens:
$ podman run --name=nginx -p 80:80 -v $HOME/nginx:/etc/nginx/conf.d:Z -d docker.io/library/nginx
a6575989327eb14b9d980505832e8b5600e17248667feba487c38c1792274b99
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4b4c00f0faa5 docker.io/library/httpd:latest httpd-foreground 30 minutes ago Up 30 minutes 0.0.0.0:8080->80/tcp syscom
ff1d8bae380a docker.io/library/httpd:latest httpd-foreground 30 minutes ago Up 30 minutes 0.0.0.0:8081->80/tcp sysorg
a6575989327e docker.io/library/nginx:latest nginx -g daemon o... 29 seconds ago Up 28 seconds 0.0.0.0:80->80/tcp nginx
Nice, it's running! Perform a simple test by trying to curl both of the apps' domains without specifying the higher ports and see if they both respond in port 80, like this:
$ curl http://sysadmin.com
<html>
<header>
<title>SysAdmin.com</title>
</header>
<body>
<p>This is the SysAdmin website hosted on the .com domain</p>
</body>
</html>
$ curl http://sysadmin.org
<html>
<header>
<title>SysAdmin.org</title>
</header>
<body>
<p>This is the SysAdmin website hosted on the .org domain</p>
</body>
</html>
As a final test, try to access both applications externally through a web browser and see if they respond correctly. But first, if you're running a firewall, allow access in port 80 through the HTTP service:
$ sudo firewall-cmd --add-service=http --permanent
success
$ sudo firewall-cmd --reload
success
Here's what it looks like when I view the sysadmin.com application in a browser:
And here's what the sysadmin.org application looks like:
Sweet! In this final architecture, the applications are responding correctly on port 80 of the same host using Nginx as a reverse proxy for both.
Wrap up
When you need to host different applications from different domains on the same host, managing them using different ports can be challenging. With the use of a reverse proxy like Nginx, combined with the advantages of running containers with Podman, you can create a multidomain architecture in a simple way.
For more sophisticated scaling, orchestration, routing, and balancing of many container-based applications and services, you can use a Kubernetes-based enterprise orchestration platform such as the Red Hat OpenShift Container Platform.
Stay tuned for more articles on related topics! In my next article, I'll show how to use Ansible to automate Podman for container and pod deployments using the environment from this article as an example.
[ Learn how to set up Nginx on OpenShift and AWS ROSA. ]
저자 소개
Alexon has been working as a Senior Technical Account Manager at Red Hat since 2018, working in the Customer Success organization focusing on Infrastructure and Management, Integration and Automation, Cloud Computing, and Storage Solutions. He is a part of the TAM Practices LATAM team based in São Paulo, Brazil, where his job is partnering with, advocating, trust-advising, and supporting customers in their success goals while making use of the complete portfolio. He also contributes to produce and enhance documentation, knowledge-base articles, blog posts, presentations, webinars, and workshops. He is a member of numerous communities in addition to the Sudoers, like Red Hat Academy and Red Hat Accelerators. When he’s not at work, he enjoys spending quality time with his family (wife, daughter, and cat) and participating in several volunteer jobs.
유사한 검색 결과
Red Hat and Sylva unify the future for telco cloud
Bridging the gap: Secure virtual and container workloads with Red Hat OpenShift and Palo Alto Networks
Can Kubernetes Help People Find Love? | Compiler
Scaling For Complexity With Container Adoption | Code Comments
채널별 검색
오토메이션
기술, 팀, 인프라를 위한 IT 자동화 최신 동향
인공지능
고객이 어디서나 AI 워크로드를 실행할 수 있도록 지원하는 플랫폼 업데이트
오픈 하이브리드 클라우드
하이브리드 클라우드로 더욱 유연한 미래를 구축하는 방법을 알아보세요
보안
환경과 기술 전반에 걸쳐 리스크를 감소하는 방법에 대한 최신 정보
엣지 컴퓨팅
엣지에서의 운영을 단순화하는 플랫폼 업데이트
인프라
세계적으로 인정받은 기업용 Linux 플랫폼에 대한 최신 정보
애플리케이션
복잡한 애플리케이션에 대한 솔루션 더 보기
가상화
온프레미스와 클라우드 환경에서 워크로드를 유연하게 운영하기 위한 엔터프라이즈 가상화의 미래