少湖说 | 科技自媒体

互联网,科技,数码,鸿蒙

  1. 删除旧版
1
sudo yum remove docker docker-common  docker-selinux  docker-engine
  1. 安装库
1
sudo yum install -y yum-utils  device-mapper-persistent-data  lvm2
  1. 配置stable repo
1
sudo yum-config-manager --add-repo  https://download.docker.com/linux/centos/docker-ce.repo
  1. 安装
1
sudo yum install docker-ce
  1. 启动
1
sudo systemctl start docker
  1. 开机启动
1
sudo systemctl enable docker

7 . hello world

1
sudo docker run hello-world

简述

本文讲述了如何使用 GitLab-CI 对 ReactNative 项目,自动打包和部署,由于安卓环境更易于在Docker上搭建环境,所以先实现了安卓应用的打包和部署。

环境依赖

  1. Docker环境使用 registry.gitlab.com/wldhx/gitlab-ci-react-native-android:master 镜像, 该镜像包含了 ReactNative 打包安卓应用所需要的所有依赖
  2. 注册一个 fir.im 账号
  3. Python3。 部署应用采用的 fir.im 平台发布,因此实现了一段用于自动上传 apk 的 Python 脚本
  4. Node。 用于安卓依赖和格式化检查

编写GitLab-CI 脚本

$ cat .gitlab-ci.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
image: node

stages:
- test
- build
- deploy

cache:
key: ${CI_PROJECT_ID}
paths:
- android/.gradle/

variables:
NPM_CONFIG_CACHE: "/cache/npm"
YARN_CACHE_FOLDER: "/cache/yarn"
DOCKER_DRIVER: overlay2
lint:
stage: test
dependencies: []
cache:
key: "$CI_COMMIT_REF_NAME"
policy: pull
paths:
- node_modules
script:
- if [ ! -d "node_modules" ]; then
- yarn install --cache-folder /cache/yarn
- fi
- yarn run lint
except:
- master
- tags
tags:
- docker

build-package:
stage: test
dependencies: []
cache:
key: "$CI_COMMIT_REF_NAME"
policy: pull
paths:
- node_modules
script:
- yarn install
artifacts:
name: "node_modules"
untracked: false
expire_in: 60 mins
paths:
- node_modules
only:
- master
- tags
tags:
- docker

build-android:
image: registry.gitlab.com/wldhx/gitlab-ci-react-native-android:master
stage: build
dependencies:
- build-package
script:
- cd android && ./gradlew assembleRelease --no-daemon
artifacts:
expire_in: 7 days
paths:
- android/app/build/outputs/apk/
only:
- master
- tags

release-android:
image: python:3
stage: deploy
cache: {}
dependencies:
- build-android
script:
- pip install -r requirements.txt
- if [[ -z "$CI_COMMIT_TAG" ]];then
- echo $(git log -3 --pretty=%s | tail -1) > ./release.txt
- else
- echo $(git tag -l --format='%(contents)' $CI_COMMIT_TAG) > ./release.txt
- fi
- python ./upload.py
only:
- master
- tags

该脚本分为三个阶段,第一阶段进行格式化检查,和安装 npm 依赖,第二阶段用于构建 apk, 第三阶段将apk上传到 fir.im 平台上,
其中 release.txt 用于存储最近的更新日志,便于在上传 apk 时,加上对应信息。

requirement.txt 文件中则使用了request库:

$ cat requirement.txt

1
requests

upload.py 文件则调用fir.im的上传API, 则 apk 上传到改平台,需要注意的时,api_token 需要在 fir.im 平台的右上角个人信息处获取

$ cat upload.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

import requests
import os


def file_get_contents(filename):
with open(filename) as f:
return f.read()


r = requests.post(
'https://api.fir.im/apps',
data={'type': 'android',
'bundle_id': 'com.company.package',
'api_token': '个人的API TOKEN'
}
)

data = r.json()

if os.environ.get('CI_COMMIT_TAG') is None:
tag = 'latest'
else:
tag = os.environ['CI_COMMIT_TAG']

changelog = file_get_contents('./release.txt')

files = {'file': open(
'./android/app/build/outputs/apk/release/app-release.apk', 'rb')}
r2 = requests.post(
data['cert']['binary']['upload_url'],
data={
'key': data['cert']['binary']['key'],
'token': data['cert']['binary']['token'],
'x:name': '应用名称',
'x:version': tag,
'x:build': 'com.company.package',
'x:changelog': changelog
},
files=files
)

print(r2.json())

参考内容

使用

  • 手机号参数对11位大陆手机号兼容
  • 支持国际手机号,请使用形如(加号)(地区编码)(一个空格)(手机号)的手机格式,例如
地区 合法格式
中国大陆 18682300424
中国大陆 +86 18682300424
美国 +1 2067925640
加拿大 +1 12042345678
英国 +44 7400123456
澳大利亚 +61 412345678

所以手机格式为:以加号开头,前面是地区区号,后面是手机号码,中间保留一个空格

  • 如果国际手机号出现在URL中,请对手机号进行编码(urlencode)

存储和处理手机号码

  • 地区编号和手机号应当分开存储
  • 增加对原11位手机号的兼容性(例如默认自动添加+86前缀)
  • 存储用户信息时,需要将phonecountry_code两个信息分别存储

验证和格式化手机号

  • 使用类库https://github.com/googlei18n/libphonenumber 或者其他语言的实现: https://github.com/googlei18n/libphonenumber#third-party-ports

使用国际手机号测试

  • 搜索可以在线接收短信验证码的平台
  • 在线接收短信验证码,进行后续测试
  • 验证码接收网站参考网址:
  • http://receive-sms.com/
  • https://tieba.baidu.com/p/3752380669
  • http://uuxn.com/seven-recerve-sms-online-free-phone
  • http://www.mfwu.net/receive-sms.html

简介

Kong 是一个微服务API网关。

Kong是一个云原生,快速,可扩展和分布式微服务抽象层(也称为API网关,API中间件或在某些情况下为Service Mesh)。
作为2015年的开源项目,其核心价值在于高性能和可扩展性。
Kong积极维护,广泛应用于从创业公司到Global 5000以及政府组织等公司的生产。

Konga 是一个用于管理网关Kong的管理端,通过它可以方便的进网关进行管理配置。

使用网关能解决很多问题:

  1. 解决端口和域名问题,代理后消除端口,将域名映射到端口,将服务映射成目录
  2. 微服务代理,将微服务置于内网,统一由网关代理
  3. 授权,可以配置授权管理,主要用于API授权
  4. 负载均衡,可以增强高访问量下的可用性,解决部署时的服务中断问题

本文主要讲述使用 Konga 对 Kong 进行网关管理配置

安装

安装过程具体请参考官网文档,如果使用docker安装 Kong 和 Konga,可以参考 配置docker-compose

配置反向代理

在 APIS 一栏,点击 ADD NEW API 按钮,添加一个代理:

  • 其中,Name 为显示名称,可任意填写;
  • Hosts 为所要使用的域名,如果不填写,则使用网关绑定的域名;如果填写,则可通过该域名访问;
  • Uris 为访问路径,如果需要将某个服务映射为一个目录,则此处需要配置;
  • Upstream URL 为上游地址,即微服务实际地址,另外可将微服务置于内网,此处即为内网地址。

需要注意的是,如果页面中有301/302跳转,需要将 Preserve Host 勾选,以保证跳转后,header中携带的 Location 中的域名为代理后的域名,否则会出现实际域名/内网域名,造成混乱,甚至暴露微服务地址

示例一:普通反向代理

配置项 内容 说明
Name dashboard 只是为了方便识别
Hosts dashboard.xxx.com 绑定的域名,类似于vhosts
Uris / 绑定目录
Methods 请求方法,默认不填
Upstream URL http://192.168.0.2:8080 实际微服务地址,建议使用内网ip, 并将该服务屏蔽外网访问
Strip uri YES
Preserve Host YES 转发时保留域名,处理301问题
Https only YES 如果不使用https,不勾选

配置负载均衡

需要注意的是,如果要使用负载均衡,需要配置 上游 (UPSTREAMS)。

在 UPSTREAMS 一栏,点击添加,Name 为一个域名形式的上游名称,如 dashboard.upstream.xxx.com, 添加完后,点击详情里面的Targets,添加一个目标,
Target 为实际的微服务地址,如 192.168.0.1:8080, 注意这里不写http协议,只写ip或域名。

一个 UPSTREAMS 可以配置多个 Targets, 针对每个 Targets 设置不同的 Weight,即实现了负载均衡。

示例二:负载均衡

UPSTREAMS 配置

配置项 内容 说明
Name coupon.api.foundation.com 类域名的别名

Targets 配置

配置项 内容 说明
Target 192.168.0.2:8001 微服务1的地址(建议使用内网)
WEIGHT 100 权重

Targets2 配置

配置项 内容 说明
Target 192.168.0.3:8001 微服务1的地址
WEIGHT 100 权重

Apis 配置

配置项 内容 说明
Name coupon 名称,任意
Hosts 留空使用网关默认的域名,如 api.xxx.com
Uris /coupon 通过 api.xxx.com/coupon 访问该服务
Methods 留空不限制
Upstream URL http://coupon.api.foundation.com/api/ 这里为配置的 UPSTREAMS 里的 Name
Strip uri YES
Preserve Host YES
Https only YES 如果不使用https,不勾选

参考文档

使用Taro和Typescript进行小程序开发

使用指南

在使用 taro 生成 Typescript 模板以后,需要做以下修改:

配置 .eslintrc

  • 加入 "no-undef": 0, 以解决变量undefined的问题
  • 加入 "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }] 以解决 JSX not allowed in files with extension '.tsx

增加配置文件

  • tsconfig.json
  • tslint 文件

增加依赖库

  • yarn add –dev tslint
  • yarn add –dev tslint-react
  • yarn add –dev ptypescript-eslint-parser

开始使用

1
2
3

yarn install

代码静态检查

1
2
yarn run lint

参考文档

2020 更新

微信出了 miniprogram-ci ,可以通过命令行调用,故而改用改方案, 见 [GitLab-CI微信小程序进行持续集成和持续部署2]

问题缘由

在微信小程序开发中,先要在本地使用微信开发者工具进行调试,如果需要在线测试,则需要将编译好的代码上传。
目前,只能通过微信开发者工具手动点击上传,而该过程无法与持续集成/持续部署结合在一起,本文就是为了解决能够实现自动化和持续部署的难题

实现原理

微信开发者工具,提供了HTTP调用方式,其中就包括上传和自动化测试的命令,我们可以通过脚本实现自动化集成

步骤

安装并配置 GitLab Runner

这部分文档在 Install GitLab Runner on macOS

安装

首先需要在本机上安装 GitLab Runner, 由于微信开发者工具只提供了 mac 和 windows 版本,所以目前只能在这两种系统上实现持续集成,本文讲述在 mac 的具体实现, windows 上的实现与此类似,只是相关命令和路径需要做些变更

注册 GitLab Runner

1
2
gitlab-runner register

注意,注册时没有sudo, 因为需要使用用户模式来使用,而非系统模式

注册时,将本机添加上了 mac 标签, 运行模式为shell,这样可以在部署时,指定运行环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
https://xxxxxx.com/
Please enter the gitlab-ci token for this runner:
xxxxxx
Please enter the gitlab-ci description for this runner:
[xxx.com]: macbook.home
Please enter the gitlab-ci tags for this runner (comma separated):
mac,shell
Whether to run untagged builds [true/false]:
[false]: true
Whether to lock the Runner to current project [true/false]:
[true]: false
Registering runner... succeeded runner=Gd3NhK2t
Please enter the executor: docker-ssh, virtualbox, docker+machine, docker-ssh+machine, docker, parallels, shell, ssh, kubernetes:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

运行服务

1
2
3
4
cd ~
gitlab-runner install
gitlab-runner start

编写 .gitlab-ci.yml

在此之前,你需要对GitLab-CI有一定的掌握,这部分资料参考下方的相关文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
image: node:alpine

before_script:
- export APP_ENV=testing
- yarn config set registry 'https://registry.npm.taobao.org'
stages:
- build
- deploy

variables:
NPM_CONFIG_CACHE: "/cache/npm"
YARN_CACHE_FOLDER: "/cache/yarn"
DOCKER_DRIVER: overlay2
build-package:
stage: build
dependencies: []
cache:
key: "$CI_COMMIT_REF_NAME"
policy: pull
paths:
- node_modules
script:
- if [ ! -d "node_modules" ]; then
- yarn install --cache-folder /cache/yarn
- fi
- yarn build
- cp deploy/project.config.json ./dist/project.config.json
artifacts:
name: "wxpkg-dlkhgl-$CI_COMMIT_TAG"
untracked: false
paths:
- dist
only:
- tags
tags:
- docker
deploy:
stage: deploy
dependencies:
- build-package
variables:
GIT_STRATEGY: none
before_script: []
script:
# 获取HTTP服务的端口, 该端口是不固定的
# - PORT=`cat ~/Library/Application\ Support/微信web开发者工具/Default/.ide`
# 调用上传的API
# - curl http://127.0.0.1:$PORT/upload\?projectpath\=$PWD/dist\&version\=$CI_COMMIT_TAG\&desc\=audo-deploy
# 以下改用命令行替代旧的 HTTP 调用方式
- /Applications/wechatwebdevtools.app/Contents/MacOS/cli -u $CI_COMMIT_TAG@/$PWD/dist --upload-desc "aoto deploy"
only:
- tags
tags:
- mac

注意,deploy/project.config.json 文件为 project.config.json的副本,但其他的 projectname 不同,这样做是为了解决 已存在相同 AppID 和 projectname 的项目(路径),请修改后重试的问题,这是因为,同一台电脑上,微信开发者工具不能有两个同名的项目

另外注意,在运行自动部署时,微信开发者工具必须打开,且为登录状态

相关文档

起因

前两天收到跨境电商事业部同事发来的一个需求,说有一个表格,里面只有产品ID和其他一些信息,但是没有其他信息,诸如产品中文名和发货地,这些信息需要通过调取API获得。希望我们帮忙导出合并到Excel中

分析及实现

  • 首先需要读取Excel中,每个产品的ID
  • 然后调用产品查询API,该API通过GET+ID参数方式进行查询
  • 查询到信息后,将需要的信息追加到对应行的后面列中

openpyxl

Python 中操作 Excel 的库有许多,例如 xlrd、xlwt、xlsxwriter、openpyxl 等,openpyxl是其中一个,该库主要有几个特点:支持xlsx,支持对现有文档读写,被Python-Excel优先推荐。
几经对比调研,最终选择 openpyxl。

使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 打开excel
wb = load_workbook('files/file.xlsx')
# 拿到打开的sheet
sheet = wb.active
for index in range(0, sheet.max_row):
# load_data 通过requests调用API方法,拿到name和ship_from
name, ship_from = load_data(sheet['A' + str(index + 1)].value)
# 产品中文名称
sheet['D' + str(index + 1)] = name
# 发货地信息
sheet['E' + str(index + 1)] = ship_from
print("同步第" + str(index + 1) + "行")
# 将数据保存到另外一表格中,注意也可以保存到原来表格中
wb.save("files/file-export.xlsx")

在上述代码中,首先加载原始文件files/file.xlsx,然后对默认sheet进行行遍历,每一行第一列An代表产品ID,
load_data方法通过调用API, 查询到该产品的中文名称和发货地,然后再写入后面的列中,如Dn和En

最后全部遍历完后,再保存表格,这样整个需求就实现了

PHP运行环境镜像构建

PHP7中访问SqlServer需要安装sqlsrv 和 pdo_sqlsrv,在此之前需要安装一此必备依赖,如msodbcsql 和 unixodbc-dev,由于SqlServer暂时不支持alpine,所以选择jessie,尽量使镜像保持最小,构建脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
FROM php:7.1-fpm-jessie

ENV ACCEPT_EULA=Y

# Microsoft SQL Server Prerequisites
RUN apt-get update \
&& curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - \
&& curl https://packages.microsoft.com/config/debian/8/prod.list \
> /etc/apt/sources.list.d/mssql-release.list \
&& apt-get install -y --no-install-recommends \
locales \
apt-transport-https \
&& echo "en_US.UTF-8 UTF-8" > /etc/locale.gen \
&& locale-gen \
&& apt-get update \
&& apt-get -y --no-install-recommends install msodbcsql unixodbc-dev

RUN docker-php-ext-install mbstring \
&& pecl install sqlsrv pdo_sqlsrv \
&& docker-php-ext-enable sqlsrv pdo_sqlsrv

启动本地开发需要的SqlServer服务

由于微软官方提供的SqlServer镜像,无法通过环境变量配置的方便创建数据库,故选择mcmoe/mssqldocker镜像,

使用docker-compose配置方式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: '3.2'

services:
db:
build: .
image: mcmoe/mssqldocker
environment:
ACCEPT_EULA: Y
SA_PASSWORD: 2astazeY
MSSQL_DB: dev
MSSQL_USER: Kobeissi
MSSQL_PASSWORD: 7ellowEl7akey
ports:
- "1433:1433"
container_name: mssqldev

需要注意的是,MSSQL密码(即上面的SA_PASSWORD和MSSQL_PASSWORD)必须至少8个字符长,包含大写,小写和数字,否则数据库会创建失败

连接访问数据库

在程序中配置数据库的地方,配置DSN如下

1
2
sqlsrv:Server=mssql;Database=dev

sqlsrv 为驱动名称

注:如果是使用Yii2框架,可以使用我构建好的镜像:zacksleo/php:7.1-fpm-mssql

需求

团队使用React开发了一套前端页面, 为了方便协作和部署, 使用 EsLint 进行代码格式审查, 同时进行持续集成和部署, 提高开发效率

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
image: zacksleo/node

before_script:
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" > ~/deploy.key
- chmod 0600 ~/deploy.key
- ssh-add ~/deploy.key
- mkdir -p ~/.ssh
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
- export APP_ENV=testing
- yarn config set registry 'https://registry.npm.taobao.org'
stages:
- prepare
- test
- build
- deploy

variables:
COMPOSER_CACHE_DIR: "/cache/composer"
DOCKER_DRIVER: overlay2
build-cache:
stage: prepare
script:
- yarn install --cache-folder /cache/yarn
cache:
key: "$CI_COMMIT_REF_NAME"
paths:
- node_modules
except:
- docs
- tags
when: manual
eslint:
stage: test
dependencies: []
cache:
key: "$CI_COMMIT_REF_NAME"
policy: pull
paths:
- node_modules
script:
- if [ ! -d "node_modules" ]; then
- yarn install --cache-folder /cache/yarn
- fi
- yarn eslint ./
except:
- docs
- develop
- master
- tags
build-check:
stage: test
dependencies: []
cache:
key: "$CI_COMMIT_REF_NAME"
policy: pull
paths:
- node_modules
script:
- if [ ! -d "node_modules" ]; then
- yarn install --cache-folder /cache/yarn
- fi
- yarn build
except:
- docs
- develop
- master
- tags
build-package:
stage: test
script:
- if [ ! -d "node_modules" ]; then
- yarn install --cache-folder /cache/yarn
- fi
- if [ $CI_COMMIT_TAG ];then
- cp deploy/production/.env .env
- fi
- yarn build
dependencies: []
cache:
key: "$CI_COMMIT_REF_NAME"
policy: pull
paths:
- node_modules
artifacts:
name: "build"
untracked: false
expire_in: 60 mins
paths:
- build
except:
- docs
only:
- develop
- master
- tags
production-image:
stage: build
image: docker:latest
dependencies:
- build-package
before_script: []
script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
- docker rmi $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
only:
- tags
production-server:
stage: deploy
dependencies: []
cache: {}
script:
- cd deploy/production
- rsync -rtvhze ssh . root@$DEPLOY_SERVER:/data/$CI_PROJECT_NAME --stats
- ssh root@$DEPLOY_SERVER "docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY"
- ssh root@$DEPLOY_SERVER "export COMPOSE_HTTP_TIMEOUT=120 && export DOCKER_CLIENT_TIMEOUT=120 && echo -e '\nTAG=$CI_COMMIT_TAG' >> .env && cd /data/$CI_PROJECT_NAME && docker-compose pull web && docker-compose stop && docker-compose rm -f && docker-compose up -d --build"
only:
- tags
environment:
name: staging
url: https://xxx.com

说明

首先使用EsLint进行代码格式检查, 每次合并到主干分支, 进行构建检查, 每次添加Tags, 构建Docker镜像,并进行部署

配置

在项目根目录,新建.styleci.yml 配置文件,并编写配置内容:

1
2
preset: psr2

查看

打开https://styleci.io/,使用Gitlab账号登录,找到对应的项目,点击右侧的 ENABLE STYLECI 启用按钮,即可使用,

每次提交代码,都会看到检测结果

提示

如果没有找到自己的项目,打开 https://styleci.io/account#repos 点击 Sync With GitHub 同步,就会看到

0%