ssh客户端配置#
拉取ssh镜像#
1
| docker pull testcontainers/sshd:latest
|
启动容器#
1
| docker run -it --name sshd testcontainers/sshd:latest sh
|
配置服务器密钥#
生成密钥#
1
| ssh-keygen -t rsa -b 4096
|
生成后选择存储路径,回车默认即可
存储密钥后输入密码,由于是自动化脚本无需设置,直接回车
复制密钥#
1
| ssh-copy-id user@remote_host
|
执行后输入yes
确定链接
连接后输入password完成连接
执行命令#
非交互式命令#
1
| ssh user@remote_host 'ls -l /path/to/directory'
|
文件传输#
1
| scp local_file user@remote_host:/path/to/remote/directory
|
打包容器并将镜像上传仓库#
若无需上传私有仓库可跳过此步骤
打包容器#
1
| docker commit sshd registry_host/sshd:latest
|
registry_host为镜像仓库地址
登录远程仓库#
1
| docker login registry_host
|
按照提示输入用户名和密码
推送镜像#
1
| docker push registry_host/sshd:latest
|
配置Gitness#
关于基础项目创建与仓库配置可参考Gitness文档,这边不再赘述。
配置流水线脚本之前先去对应的流水线设置触发器,不然就会出现脚本配置完成但是推送不触发流水线的尴尬情况= =
配置处在Pipelines -> 三个点 -> Settings -> Triggers
本机拉取镜像出错解决方法#
如果你的镜像仓库和Gitness在同一台主机或者网络环境下,且配置了反向代理,才会出现这个问题
直接按照域名/镜像名称
拉取会报错Error response from daemon: Get "https://域名/v2/": net/http: TLS handshake timeout
这个时候需要更改拉取方式,将拉取地址修改为内网IP:端口/镜像名称
同时修改配置/etc/docker/daemon.json
1
2
3
| {
"insecure-registries": ["内网IP:端口"]
}
|
并重启docker
登陆时使用内网IP:端口
进行登录,在后期拉取时也使用内网IP:端口/镜像名称
进行拉取
配置完毕后,只有跟镜像在同一台主机或网络环境下的拉取与推送需要切换拉取方式,其他主机依旧使用域名进行拉取或推送,登录同理
流水线时实践#
启动前可以先手动拉取drone/git:latest
与其他所需镜像,避免Gitness直接拉取失败。
Hugo自动化部署#
流水线配置#
1
2
3
4
5
6
7
8
9
10
11
12
13
| kind: pipeline
spec:
stages:
- type: ci
spec:
steps:
- name: prod
type: run
spec:
container: registry_host/sshd:latest
privileged: true
script: |-
ssh -t -o StrictHostKeyChecking=no user@host 'cd /website/InitCompose && bash blog.sh'
|
脚本文件配置#
blog.sh#
1
2
| docker compose run --rm hugo sh /script/hugo.sh
docker restart blog-nginx
|
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
| #!/bin/sh
# 定义变量
REPO_DIR="/repo"
REPO_URL="https://username:token@仓库路径.git"
BRANCH="master"
SRC_DIR="/src"
# 检查 REPO_DIR 是否存在,如果不存在则创建它
if [ ! -d "$REPO_DIR" ]; then
echo "$REPO_DIR 不存在,开始创建..."
mkdir -p "$REPO_DIR"
fi
# 检查路径中是否有现有的 git 仓库
if [ -d "$REPO_DIR/.git" ]; then
echo "Git 仓库存在,将删除并重新克隆..."
# 删除现有仓库
rm -rf "$REPO_DIR"
# 重新创建目录
mkdir -p "$REPO_DIR"
fi
# 进入目录
cd "$REPO_DIR" || { echo "进入目录失败"; exit 1; }
echo "正在克隆仓库..."
# 克隆远程仓库
git clone "$REPO_URL" .
# 检查克隆是否成功
if [ $? -ne 0 ]; then
echo "克隆远程仓库失败"
exit 1
fi
# 切换到指定分支
git checkout "$BRANCH" || { echo "切换到分支 $BRANCH 失败"; exit 1; }
# 删除 src 目录下的所有内容
echo "删除 $SRC_DIR 下的所有内容..."
rm -rf "$SRC_DIR/*"
# 复制 WebBlog 目录下的内容到 src 目录
echo "将 $REPO_DIR/WebBlog 下的内容复制到 $SRC_DIR..."
cp -rf "$REPO_DIR/WebBlog/"* "$SRC_DIR/"
# 确保复制操作成功
if [ $? -ne 0 ]; then
echo "复制文件失败"
exit 1
fi
# 确保 hugo 已经安装
if ! command -v hugo > /dev/null 2>&1; then
echo "hugo 命令未找到,请确保 hugo 已经安装"
exit 1
fi
cd "$SRC_DIR" || { echo "进入目录失败"; exit 1; }
echo "重新构建 hugo 站点..."
rm -rf public
hugo
echo "构建完成"
|
操作完成后,Gitness会在每次提交自动化部署,极大减少每次博客更新发布的复杂度
Java项目部署#
需要准备好一个配置好目标主机ssh密钥的ssh客户端镜像
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
| kind: pipeline
spec:
options:
envs:
PROJECT_NAME: <项目名>
USER_NAME: <ssh 用户名>
HOST_NAME: <ssh 主机名>
SERVER_PORT: <服务端口>
stages:
- type: ci
spec:
volumes:
- name: resp
spec:
path: /root/.m2/repository
type: host
- name: cache
spec: {}
type: temp
steps:
- name: build
type: run
spec:
container: maven:3.9.8-sapmachine-17
privileged: true
mount:
- name: cache
path: /tmp
- name: resp
path: /root/.m2/repository
script: |-
mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V
mvn test -B
mkdir -p /tmp/maven-build
cp ${PROJECT_NAME}/target/*.jar /tmp/maven-build/
artifacts:
- ${PROJECT_NAME}/target/*.jar
- name: mkdir
type: run
spec:
container: <镜像仓库域名>/ssh:latest
privileged: true
script: ssh -t ${USER_NAME}@${HOST_NAME} "rm -r /website/${PROJECT_NAME}/backend && mkdir -p /website/${PROJECT_NAME}/backend"
- name: push-run
type: run
spec:
container: <镜像仓库域名>/ssh:latest
privileged: true
mount:
- name: cache
path: /tmp
script: |-
scp -o StrictHostKeyChecking=no /tmp/maven-build/${PROJECT_NAME}.jar ${USER_NAME}@${HOST_NAME}:/website/${PROJECT_NAME}/backend
ssh -t ${USER_NAME}@${HOST_NAME} "docker rm -f java-${SERVER_PORT} && docker run --name java-${SERVER_PORT} -v /website/${PROJECT_NAME}/backend:/website/${PROJECT_NAME}/backend -p ${SERVER_PORT}:${SERVER_PORT} --restart always -d bellsoft/liberica-openjdk-debian:17 sh -c 'java -jar /website/${PROJECT_NAME}/backend/${PROJECT_NAME}.jar'"
|
前端(Nginx)项目部署#
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
| kind: pipeline
spec:
options:
envs:
PROJECT_NAME: <项目名>
USER_NAME: <ssh 用户名>
HOST_NAME: <ssh 主机名>
SERVER_PORT: <服务端口>
stages:
- type: ci
spec:
volumes:
- name: resp
spec:
path: /root/.node/node_modules
type: host
- name: cache
spec: {}
type: temp
steps:
- name: build
type: run
spec:
container: node:16.20.2
privileged: true
mount:
- name: cache
path: /tmp
- name: resp
path: /gitness/node_modules
script: |-
npm install
npm run build:prod
cp -r dist /tmp/node-build
ls /tmp/node-build
- name: mkdir
type: run
spec:
container: <镜像仓库域名>/ssh:latest
privileged: true
script: ssh -t ${USER_NAME}@${HOST_NAME} "rm -r -f /website/${PROJECT_NAME}/frontend && mkdir -p /website/${PROJECT_NAME}/frontend"
- name: push-run
type: run
spec:
container: <镜像仓库域名>/ssh:latest
privileged: true
mount:
- name: cache
path: /tmp
script: |-
scp -r -o StrictHostKeyChecking=no /tmp/node-build ${USER_NAME}@${HOST_NAME}:/website/${PROJECT_NAME}/frontend
ssh -t ${USER_NAME}@${HOST_NAME} "docker rm -f node-${SERVER_PORT} && docker run --name node-${SERVER_PORT} -v /website/${PROJECT_NAME}/frontend/node-build:/usr/share/nginx/html -p ${SERVER_PORT}:80 --restart always -d nginx:latest"
|