返回文章列表文章索引阅读全文
STARBLOG / 阅读手记
项目开发小结系列

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.

曦远 (DealiAxy)约 20 分钟
目录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 export is smaller than the one saved with save, because save exports all layers.
  • Multiple images: save can package multiple images into a single file, while export cannot.
  • 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 分钟

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…

Project Summary: Using Docker to Migrate Services to an Offline Server · StarBlog