How We Cut Deployment Time from Days to Minutes with FRP, Docker, and Ansible
This article details a three‑stage evolution of environment deployment—from manual installation to VM image restoration and finally to automatic registration with command issuance—showing how FRP tunneling, Docker containers, Ansible automation, and a custom deploy tool dramatically reduce deployment effort and eliminate the need for dedicated ops staff.
Preface
We have gone through three stages in solving environment deployment problems: traditional installation, image restoration, and automatic discovery registration with command issuance. After image restoration, once a VM can ping our company address it automatically registers, giving us management rights and enabling batch command distribution.
Background
We are a product‑plus‑custom‑requirements company. After a project is completed we deploy directly to the client’s servers. Clients usually provide 1‑2 virtual machines in their own data center, leaving the entire environment setup to us.
Evolution
Stage 1: Traditional Installation (≈2016)
Clients provide various remote‑access methods (bastion host, VPN, direct ports, etc.).
Remote into the server.
Upload database, JDK, Tomcat packages (often slow due to bandwidth).
Install the database.
Install JDK, Tomcat, Nginx (run prepared shell scripts on Linux, still time‑consuming).
Manually deploy WAR packages and other artifacts.
This method is cumbersome, often requiring 3‑5 person‑days, which is impractical for a team with only one ops engineer.
Stage 2: Image Restoration (2016‑2017)
Clients still provide remote‑access methods.
Restore a VM from a prepared image (including Docker).
Deploy WAR packages with a one‑click deploy module.
We packaged steps 2‑5 of Stage 1 into a VM image, built a deploy module, and made the project stateless. Ops dependence dropped dramatically, reducing work to 2‑6 hours.
Stage 3: Automatic Discovery Registration + Command Issuance (2017‑2018)
Clients restore our VM image, set the IP, and ensure it can ping our company address.
Automatic discovery registration and command issuance.
One‑click WAR deployment via the deploy module.
Deployment time fell to 5‑10 minutes, we no longer needed client‑side remote access, and we could batch‑manage all machines, laying the groundwork for future scaling.
Specific Technologies (Stages 2 & 3)
FRP
FRP is an internal‑network‑penetration tool. We use it to expose a machine without a public IP to another internal network.
Installing the FRP Server
wget --no-check-certificate https://raw.githubusercontent.com/clangcn/onekey-install-shell/master/frps/install-frps.sh -O ./install-frps.sh
chmod 700 ./install-frps.sh
./install-frps.sh installAll parameters accept defaults.
Installing the FRP Client (Linux example)
Download frp_0.14.0_linux_amd64.tar.gz, keep the files prefixed with frpc, and extract them to ~/frp.
reg.sh Script
UUID=$(cat /sys/class/dmi/id/product_uuid)
wget -O frpc.ini http://114.114.114.114/frp.php?file=$UUID
a=$(du -s frpc.ini | awk '{print $1}')
if [ $a -lt 1 ]; then
echo "none"
else
echo "action"
pkill frpc
sleep 2s
rm -rf ~/frp/frpc.ini
cp frpc.ini ~/frp/frpc.ini
~/frp/./frp.sh
fiThe UUID uniquely identifies the server, ensuring even identical VM images have distinct identifiers. The IP 114.114.114.114 is our external registration server.
crontab
*/5 * * * * ~/reg.shThe script runs every five minutes to register or fetch changes; if the server configuration is unchanged, the service does not restart.
FRP Auto‑Start (Linux)
chmod +x ~/frp/frp.sh
vi /etc/rc.d/rc.local # add at the end: bash ~/frp/frp.sh
chmod +x /etc/rc.d/rc.localSimple frp.php Backend
<?php
$filename=$_GET['file'].'.ini';
$filename='frp/'.$filename;
if(!file_exists($filename)){
file_put_contents($filename, "");
file_put_contents($filename.'.update', $_SERVER['REMOTE_ADDR']);
} else {
if(!file_exists($filename.'.update')){
$str = file_get_contents($filename);
echo $str;
file_put_contents($filename.'.update', $_SERVER['REMOTE_ADDR']);
}
}
?>.ini Example
[common]
server_addr = 114.114.114.114
server_port = 5443
privilege_token = <strong>secret</strong>
[webserver]
type = tcp
local_ip = 127.0.0.1
local_port = 22
use_encryption = false
use_compression = false
remote_port = 7001
[a-web]
type = http
local_ip = 127.0.0.1
local_port = 80
use_encryption = false
use_compression = true
custom_domains = a.a.comWith this configuration the internal machine’s port 22 is tunneled to 172.0.0.2:7001, and its HTTP service is reachable via a.a.com.
Ansible
Ansible is used for automated batch control; see the separate article “Practical Ansible for Automated Operations”.
External Port Mapping
Map external IP 114.114.114.114:5443 to internal 172.0.0.2:5443 while leaving other ports untouched.
Docker
Docker images enable rapid deployment of our system; see the related blog post on DevOps transformation.
Portainer
Portainer provides a web UI for Docker management; see the comparison article for alternatives.
Deploy Module
Our custom deploy tool handles automatic WAR upgrades; refer to the “Java Web Project WAR Auto‑Upgrade Solution” article for details.
Conclusion
By combining FRP tunneling, Ansible batch control, Docker rapid deployment, and a custom deploy system, we dramatically reduced operational costs and entered a DevOps era without dedicated ops personnel. This approach can help other small companies facing similar deployment challenges.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
