Project Summary: Using Docker to Migrate Services to an Offline Server
Recently encountered a scenario where I needed to migrate a previously developed system to an offline server. This server is quite tricky to access—only reachable via VPN through a bastion host, with very slow speeds. I ran into quite a few pitfalls along the way. This article documents the migration process.
目录11 个章节
Foreword
The scenario I came across recently required migrating a system I previously developed to an offline server. This server was somewhat challenging—access required connecting through VPN and then a jump server (堡垒机), and the speed was quite slow. I encountered several pitfalls along the way. This article documents the migration process.
Basic Information
Originally, this system was quite simple – a Django backend API paired with a Vue+Echarts large-screen dashboard, using MySQL as the database and Redis for caching. All of these were deployed using Docker on the original server.
This offline server runs CentOS 7.9. Although it cannot access the internet, it fortunately has a local yum repository. However, the official yum sources are very limited, allowing only a few select software installations.
Now, besides the frontend which does not need to be migrated, all other services need to be transferred to this offline server.
Migration Steps:
- Install Docker on the offline server
- Export container images from the original server
- Upload and import the images to the offline server
- Upload various Docker configurations and start the containers on the offline server
- Configure surrounding components, such as Nginx
Offline Docker Installation
As mentioned earlier, this server has a local yum mirror, but it doesn't include Docker, so you'll need to download Docker's RPM installation packages manually.
At this address: https://download.docker.com/linux/centos/7/x86_64/stable/Packages/
You need to download the following installation packages (the versions are the latest at the time of writing; please download the current latest versions yourself)
- containerd.io-1.6.21-3.1.el7.x86_64
- docker-buildx-plugin-0.10.5-1.el7.x86_64
- docker-ce-24.0.2-1.el7.x86_64
- docker-ce-cli-24.0.2-1.el7.x86_64
- docker-ce-rootless-extras-24.0.2-1.el7.x86_64
- docker-compose-plugin-2.18.1-1.el7.x86_64
Then upload all these installation packages to the server.
Execute the command to install
sudo yum install containerd.io-1.6.21-3.1.el7.x86_64.rpm docker-ce-24.0.2-1.el7.x86_64.rpm # and others...
This is to place all files in the same install command, because these packages have interdependencies. If installed one by one, errors may occur due to ordering issues.
After installation, start Docker
sudo systemctl enable docker
sudo systemctl start docker
Adding user groups is also a standard operation after installing Docker
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
After that, you can run Docker commands without using the root user.
Exporting Images
There are two ways to export images
- docker export - corresponds to docker import for importing images
- docker save - corresponds to docker load for importing images
PS: The export and import commands must be matched and cannot be interchanged
The former is mainly used to create base images. After export, there are no history records or metadata, and there is no entrypoint, so they cannot be run directly. For this service migration, the save method is used.
Command to operate
docker save <container_id> -o image.tar
You can also use redirection
docker save <container_id> > image.tar
Specific differences between these two methods
- File size: The image file exported with
exportis smaller than the one saved withsave, becausesaveexports all layers. - Multiple images:
savecan package multiple images into a single file, whileexportcannot. - export (import): Retrieves the image from a container. Upon re-importing, all image history and metadata are lost (i.e., only the container's snapshot state is preserved), making rollback operations impossible.
- save (load): Preserves the image history, allowing rollback to a previous layer (层).
Application Scenario Differences
- docker export Application Scenario: Primarily used to create base images. For example, we start a container from an ubuntu image, install some software and make some configurations, then use docker export to save it as a base image. Subsequently, this image can be distributed to others for use, such as a basic development environment.
- docker save Application Scenario: If our application is composed of multiple images orchestrated using docker-compose.yml, but the customer server we need to deploy to cannot access the external network, we can use docker save to package the required images, then copy them to the customer server and load them using docker load.
Pack Data
On the old server, Docker was used to deploy the MySQL service, with the data directory mapped out. You need to migrate this data along with everything else to the new server.
MySQL Docker volumes configuration
volumes:
- ./data:/var/lib/mysql
Because the VPN bandwidth is very low, this time tar + bzip2 is used for packing and compression.
tar -cjvf ./data data.tar.bz2
Command parameter explanation:
-c: Parameter to create an archive (create)-j: Use bzip2 compression-v: Display details during compression (verbose)-f: Specify the filename, no other parameters can follow this one
Then, upload this data.tar.bz2 to the new server.
I'll also include the decompression command.
tar -xjvf data.tar.bz2
This command will generate the data directory in the current directory.
Command parameter explanation:
-x: Indicates extraction (extract)- The other parameters are the same as above.
Importing Images
After uploading the previously exported Docker image, execute the import command
docker load < image.tar
Then run docker images to verify if the import was successful.
Starting the Container
Upload the original docker-compose configurations.
Previously, for easier updates, the Django project was built on the server directly after uploading the code, like this:
version: "3.6"
services:
web:
restart: always
build: .
environment:
- ENVIRONMENT=docker
- URL_PREFIX=demo/api
- DEBUG=false
- DEFAULT_DATABASE=mysql
command: uwsgi uwsgi.ini
volumes:
- .:/code
However, on an offline server, it's impossible to build without a network.
Therefore, we need to change build . to image: image_name.
After making this change, it started successfully~
Configure Peripheral Components
Just providing the interface isn't a big deal; all you need to do is install nginx.
However, as everyone knows, the default yum repository doesn't even have nginx. To install nginx, you need to add the epel-release repository.
sudo yum install epel-release
Fortunately, the local repository of the offline server has this package.
sudo yum update
sudo yum install nginx
Done~
Then it's the same old routine, use systemctl to start nginx, which I won't repeat.
This server has been quite a hassle. Since it's all set up, you need to test it, but the interfaces aren't open, and the SSH connection is through multiple jumps. It seems impossible to enable SSH-tunnel forwarding to test locally.
So, you can only use tools like curl to test.
However, this time I tried a different approach and used a command-line browser to see if I could open the project's webpage.
I tried these two:
- w3m
- lynx
Successfully opened the webpage, and the effect of both browsers was similar.
References
_EOF_
Project Summary: Using Docker to Migrate Services to an Offline Server
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
项目完成小结:使用Blazor和gRPC开发大模型客户端
其实几年前我就有轻度使用了一下 Blazor 这个技术,一开始使用 Blazor ,我是有点嫌弃的,我还是比较倾向于传统的前后端分离,AspNetCore用来做后端,用 React 做前端,生态很丰富,要做啥组件都容易。这次只是个小 Demo 项目,试用了一下 Blazor ,从一开始的非常别扭,到越来越顺手。感觉 Blazor Server 写小项目还是挺好用的,后面继续完善项目,持续发掘 B
2023-07-14 · 项目开发小结系列 · 约 1 分钟
项目完成小结-民政局项目-Django3.x版本-开发部署小结
前言 最近因为政企部门的工作失误,导致我们的项目差点挂掉,客户意见很大,然后我们只能被动进入007加班状态,忙得嗷嗷叫,直到今天才勉强把项目改完交付,是时候写一个小结。 技术 因为前期需求不明确,数据量不大,人手也不多,所以我直接用Django做了后端,Django自带的admin可以作为管理后台使用,可以很快完成这个需求。 我们的前端有两个,一个数据展示大屏,一个可视化地图。前者使用Vue+El
2022-04-25 · 项目开发小结系列 · 约 1 分钟
项目完成小结:使用DjangoStarter v3和Taro开发的微信小程序
后端DjangoStarter v3秒杀开发,ninja API写起来真香。前端Taro做微信小程序?呵呵,微信烂得一坨但居然有护城河?django-filer和tailwindcss还行,分享搞定,就是拖太久没动代码。
2024-09-12 · 项目开发小结系列 · 约 1 分钟
项目开发小结-8月新项目-校车项目
Model/数据库设计建议 from django.db import models from django.utils import timezone class ModelManager(models.Manager): def get_queryset(self, *args, **kwargs): return super().get_queryset(*args
2022-08-28 · 项目开发小结系列 · 约 1 分钟
讨论
共 0 条加载评论中…