If title of this blog, attracted you towards this blog, Most likely, you will be one of us, who want to migrate old traditional application’s in container environment. This blog covers my experience of Migrating old traditional application into Docker.
Before beginning with migration procedure, Let me explain requirements I had to met with migrated system.
- Old apps running on servers/VMs, resource utilization not optimal.
- High maintenance cost.
- OS running is no longer supported by vendors, so in-house support required.
- Maintenance downtime high.
- Platform to adopt DevOps practice for fast refactoring.
- Migrate Application with least changes in existing platform and infrastructure use.
- Use same OS distribution.
- No rewriting application for new OS.
- No changes in network infrastructure.
- Behavioral changes for accessing the application should be none.
- Use hardware load balancer.
- Use Fixed-IP with pre-approved MAC address.
Migrating old applications into containers can be divided into two parts. 1. Application code/binary migration into image. 2. Application deployment, as per requirements.
The first part is specific to each application, as every application have different challenges for migration. I will not discuss details of that. Though few of things need be considered before migrating.
Which OS/distribution to be chosen for docker host. Ideally any distribution which have LTS should be fine.
Though, sometime you may need to consider alternate from latest due compatibility with application. To check application compatibility, follow the below Checklist.
Application compatibility Checklist
- Check if any changes in ABI for linux kernel functionality and libraries used by application.
- If ABI breaks, either we need to choose old kernel, where you may need to work little bit to make docker work properly.
- OR, recompile application with new libraries.
- Any special Kernel settings required by application.
- Host kernel parameters may need to be tweaked and/or cgroups/namespaces need to be adjusted accordingly.
After detailed analysis, we can decide and configure Docker Host.
Application migration in my case is simple. Just containerize the whole application. i.e. Build an image/rootfs with old libraries and application code. Typically old application requires more then one process to run, using Supervisord, it can be achieved.
Now once, you successfully able build & test image for application, Lets focus on how it can be deployed with least changes to current setup.
As started in challenges section, we are using hardware load-balancer and want to continue the same. Also, this application is bind to fixed-IP and specific MAC address.
Since docker supports macvlan network driver, the above two goals can be easily achieved. Using macvlan driver, we can put a container on same network as old servers. Also macvlan user less CPU and slightly better throughput then bridge network.
Lets go through its details.
On docker host, lets create a macvlan network.
$ docker network create -d macvlan --subnet=172.20.20.0/18 --gateway=172.20.0.1 -o parent=enp1s0 -o macvlan_mode=bridge maclan 798b8a2ee7988dc0388c9985eaa7f0bc9373f11cf1be4a3b3a44abee162442fd $ docker network ls NETWORK ID NAME DRIVER SCOPE 9a9ff4851e71 bridge bridge local ddbc211bcf8f docker_gwbridge bridge local a7211f1ae74d host host local 8aetfb2dtwmu ingress overlay swarm 798b8a2ee798 maclan macvlan local d43c2f84509b none null local
NOTE: macvlan network is local to host, so this cannot be used over swarm.
Now, I need to create an network interfaces for my containers. I need to deploy two containers as replacement of two Application servers. For security reason, I need to assign predefined MAC address to this interface. But with macvlan driver this is also possible.
Now my network is ready, I can deploy my applications on same. Lets create containers on these network.
$ docker run --net=maclan --ip=172.20.20.51 --mac-address 08:00:27:0B:1C:FE -itd alpine sh 1f0307c12ea7a666bffc4224665f304aae67056a7cbc6f037ec19d73b5a8a64d $ docker run --net=maclan --ip=172.20.20.52 --mac-address 08:00:27:3F:FE:8E -itd alpine sh 72849de4f1e23b2bd2394ef579c48045260b4f8f0026a601c5ac93514bc90e0d $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 72849de4f1e2 alpine "sh" 5 seconds ago Up 2 seconds grave_pike 1f0307c12ea7 alpine "sh" 49 seconds ago Up 46 seconds elegant_yalow
Test it and containers are reachable from other machine on network.
$ ping 172.20.20.51 PING 172.20.20.51 (172.20.20.51): 56 data bytes 64 bytes from 172.20.20.51: seq=0 ttl=64 time=0.090 ms 64 bytes from 172.20.20.51: seq=1 ttl=64 time=0.057 ms 64 bytes from 172.20.20.51: seq=2 ttl=64 time=0.058 ms ^C --- 172.20.20.51 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max = 0.057/0.068/0.090 ms $ ping 172.20.20.52 PING 172.20.20.52 (172.20.20.52): 56 data bytes 64 bytes from 172.20.20.52: seq=0 ttl=64 time=0.075 ms 64 bytes from 172.20.20.52: seq=1 ttl=64 time=0.058 ms 64 bytes from 172.20.20.52: seq=2 ttl=64 time=0.066 ms ^C --- 172.20.20.52 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max = 0.058/0.066/0.075 ms
Now these containers have successfully replaced the two app servers, and for external load balancer, there is no changes.
NOTE: Alternative to macvlan is IPVlan, but since it is not yet stable in docker, I choose macvlan
So what are the Benefits, I finally achieved through this migration.
- Portability: Application,can be migrated to different machines easily.
- Flexibility: Image can be shared and experiment within team.
- Modularity: Provides a base to break application into further smaller services.
- Reuse: Reuse current infrastructure like network, load balancer. Least disturbance.
Hope this blog will help you to find some answers, if you are looking for migrating legacy/old/monolithic applications to docker.