Use scripts to package and upload Docker images with one click

Use scripts to package and upload Docker images with one click

The author has been working on a micro-frontend project for more than a year. A team manages ten micro-applications. After switching to docker image deployment, the release operation has changed from 1 minute when the original script directly connects to the server to dozens of minutes, especially when uploading each application to its respective Alibaba Cloud warehouse. Here we will write another script to package the Docker image with one click and upload it to Alibaba Cloud.

This article only talks about how to make a script to help reduce the burden on developers. For the configuration of docker-compose, see: Deploy micro-frontend projects comfortably using various postures (Part 1: Packaging and uploading)

Rendering

Directly on the code

/**
 * @name docker image packaging and upload script * @author weilan
 * @time 2021.02.22
 */
const fs = require('fs');
const path = require('path');
const util = require('util');
const { log } = require('../utils/log');
const exec = util.promisify(require('child_process').exec);
const sub_app_ath = path.resolve();
let sub_apps = fs.readdirSync(sub_app_ath).filter(i => /^subapp|master/.test(i));
const inquirer = require('inquirer'); // For command line interaction/**
 * @name command line interaction configuration item*/
const question = [
 {
  type: 'confirm',
  name: 'dist',
  message: 'Do you need to package the front-end static resources? ',
 },
 {
  type: 'confirm',
  name: 'env',
  message: 'Please select whether you need to package it for offline intranet deployment',
  when: function (answers) { // The current question will be asked only when answer is true return answers.dist
  }
 },
 {
  type: 'checkbox',
  name: 'apps',
  message: 'Please select the module to be published',
  choices: sub_apps,
  validate: function (val) {
   if (val.length) { // check return true;
   }
   return "The selection cannot be empty";
  }
 },
]

/**
 * @name Perform logical processing based on command interaction configuration results*/
inquirer.prompt(question).then(async (answer) => {
 let subApps = answer.apps;
 let buildScript = answer.env ? 'yarn build --Intranet' : 'yarn build';
 let needDist = answer.dist;
 let now = +new Date();
 // Log in to Alibaba Cloud const { error: loginError } = await exec('docker login --username=哈哈哈--password=嘿嘿registry.cn-zhangjiakou.aliyuncs.com');
 if (loginError) {
  log.red(loginError, 'Login to mirror center failed')
  return;
 }
 console.log(`Start processing ${JSON.stringify(subApps)} in sequence ......`);
 subApps.reduce((chain, item) => {
  return chain.then(() => publishIamge(item, now, needDist, buildScript))
 }, Promise.resolve())
});

/**
 * @name Package the image and push it to Alibaba Cloud* @param {String} moduleName Module name* @param {String} now Current version timestamp* @param {Boolean} needDist Whether to package the front-end static resources* @param {String} buildScript Front-end static resource packaging command*/
async function publishIamge(moduleName, now, needDist, buildScript) {
 //Package front-end static resources if (needDist) {
  console.log('Start packaging front-end static resources' + moduleName);
  const { error } = await exec(buildScript, { cwd: path.resolve(moduleName) });
  if (error) {
   log.red(moduleName, 'Front-end code packaging error:', error)
   return;
  }
  log.green(moduleName + 'Front-end code packaged successfully')
 }
 // Packaging image console.log(`Start packaging image ${moduleName} ......`);
 const { stdout: buildStdout, error: buildError } = await exec('docker-compose build ' + moduleName);
 if (buildError) {
  log.red(buildError, 'Mirror packaging error')
  return;
 }
 log.cyan(buildStdout)
 log.green('Image packaging completed, start making image tags')
 // Update image tag const imageName = 'ibp2fe_' + moduleName;
 const { error: tagError } = await exec(`docker tag ${imageName} registry.cn-zhangjiakou.aliyuncs.com/futureweb/${imageName}:${now}`);
 if (tagError) {
  log.red(tagError, 'Mirror tag exception')
  return;
 }
 log.green('Mirror version tag updated, start updating last tag')
 // Update the last version of the image tag const { error: tagLastError } = await exec(`docker tag ${imageName} registry.cn-zhangjiakou.aliyuncs.com/futureweb/${imageName}`);
 if (tagLastError) {
  log.red(tagError, 'Mirror last tag exception')
  return;
 }
 log.green('Mirror last tag updated, start uploading')
 const { stdout: pushStdout, error: pushError } = await exec('docker push registry.cn-zhangjiakou.aliyuncs.com/futureweb/' + imageName);
 if (pushError) {
  log.red(pushError, 'Image upload failed')
  return;
 }
 log.cyan(pushStdout)
 log.green('Image upload successful')
}

process.on('unhandledRejection', (reason, p) => {
 console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
 // application specific logging, throwing an error, or other logic here
});

Implementation ideas and precautions

  • First, consider the command line interaction method, let the developer confirm the configuration that needs to be done in a selective way, and finally select the modules to be released
  • Log in to your Alibaba Cloud account in advance
  • Here you can choose to execute all the selected modules concurrently, but the log output will be out of order, and the computer will temporarily freeze due to great pressure; so here I will use the sequential processing method
  • Package the front-end static resources of the selected module
  • Execute docker-compose build xxx to package the selected module image

There is one point that needs attention here. Because it is handled by tool functions, the path of each module is read by node, so your module name should be consistent with the service name and container name in docker-compose.yml. Also, please note that after your image is packaged, the underscore of the root directory outside your docker-compose.yml is connected to your docker-compose service name, so your Alibaba Cloud image repository should be named consistent with the combined image name. The above is to facilitate the tool function to universally handle the images of various modules.

  1. Create a mirror tag. Here I will create a version with the timestamp of this release and a lastet version. The former is convenient for rollback, and the latter is convenient for operation and maintenance deployment without having to worry about the tag version. You can also pull the git tag to make the image tag.
  2. After creating the image, upload it to the Alibaba Cloud Image Center
You may also be interested in:
  • Delete the image operation of none in docker images
  • Solve the problem of docker images disappearing
  • How to operate Docker and images
  • Docker image import and export code examples
  • Solution to Docker image downloading too slowly
  • Analysis of the Docker image construction principle (you can build an image without installing Docker)
  • Use the docker build kit to build a Docker image that can be used on the Raspberry Pi
  • Steps to completely uninstall the docker image

<<:  HTML code example: detailed explanation of hyperlinks

>>:  Detailed explanation of semiotics in Html/CSS

Recommend

How to install multiple mysql5.7.19 (tar.gz) files under Linux

For the beginner's first installation of MySQ...

Detailed explanation of Docker Compose deployment and basic usage

1. Docker Compose Overview Compose is a tool for ...

MySQL installation diagram summary

MySQL 5.5 installation and configuration method g...

A link refresh page and js refresh page usage examples

1. How to use the link: Copy code The code is as f...

How to use nginx to build a static resource server

Taking Windows as an example, Linux is actually t...

Some details about semicolons in JavaScript

Preface Semicolons in JavaScript are optional, an...

The main differences between MySQL 4.1/5.0/5.1/5.5/5.6

Some command differences between versions: show i...

Docker image compression and optimization operations

The reason why Docker is so popular nowadays is m...

How to change the encoding to utf-8 in mysql version 5.7 under windows

Preface I just started learning MySQL and downloa...

Tutorial on using Docker Compose to build Confluence

This article uses the "Attribution 4.0 Inter...

This article will help you understand the life cycle in Vue

Table of contents 1. beforeCreate & created 2...

Docker-compose tutorial installation and quick start

Table of contents 1. Introduction to Compose 2. C...

A detailed introduction to HTML page loading and parsing process

The order in which the browser loads and renders H...

Element sample code to implement dynamic table

Table of contents 【Code background】 【Code Impleme...