add webterminal dockerfile
This commit is contained in:
1
Makefile
1
Makefile
@@ -918,6 +918,7 @@ generate-manpage: ## generate manpage
|
||||
.PHONY: devstar
|
||||
devstar:
|
||||
docker build -t devstar-studio:latest -f docker/Dockerfile.devstar .
|
||||
docker build -t devstar.cn/devstar/webterminal:latest -f docker/Dockerfile.webTerminal .
|
||||
|
||||
.PHONY: docker
|
||||
docker:
|
||||
|
||||
@@ -73,7 +73,7 @@ RUN chown git:git /var/lib/gitea /etc/gitea
|
||||
COPY --from=build-env /tmp/local /
|
||||
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
||||
|
||||
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/webTerminal.sh /app/gitea/webTerminal.sh
|
||||
# git:git
|
||||
USER 1000:1000
|
||||
ENV GITEA_WORK_DIR=/var/lib/gitea
|
||||
|
||||
40
docker/Dockerfile.webTerminal
Normal file
40
docker/Dockerfile.webTerminal
Normal file
@@ -0,0 +1,40 @@
|
||||
FROM docker.io/library/ubuntu:24.04 AS build-env
|
||||
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
git \
|
||||
build-essential \
|
||||
cmake \
|
||||
libjson-c-dev \
|
||||
libwebsockets-dev
|
||||
|
||||
RUN git clone https://devstar.cn/devstar/webTerminal.git /home/webTerminal
|
||||
# 设置工作目录并构建
|
||||
WORKDIR /home/webTerminal/build
|
||||
RUN cmake ..
|
||||
RUN make && make install
|
||||
|
||||
|
||||
FROM ubuntu:24.04
|
||||
|
||||
# 从构建阶段复制编译好的程序
|
||||
COPY --from=build-env /home/webTerminal/build/ttyd /home/webTerminal/build/ttyd
|
||||
|
||||
# 只安装运行时需要的库
|
||||
RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
curl && \
|
||||
curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc && \
|
||||
apt-get install -y tini \
|
||||
libjson-c-dev \
|
||||
libwebsockets-dev && \
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/ \
|
||||
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
|
||||
tee /etc/apt/sources.list.d/docker.list > /dev/null && \
|
||||
apt-get update && apt-get install -y docker-ce-cli && \
|
||||
apt remove --purge curl -y && apt autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
ENTRYPOINT ["/usr/bin/tini", "--"]
|
||||
CMD ["/home/webTerminal/build/ttyd", "-W", "bash"]
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// TplDevstarHome 显示 DevStar Home 页面 templates/devstar-home-vscode.tmpl
|
||||
TplDevstarHome templates.TplName = "repo/devcontainer/devstar-home-vscode"
|
||||
// TplDevstarHome 显示 DevStar Home 页面 templates/vscode-home.tmpl
|
||||
TplDevstarHome templates.TplName = "repo/devcontainer/vscode-home"
|
||||
)
|
||||
|
||||
// DevstarHome 渲染适配于 VSCode 插件的 DevStar Home 页面
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package devcontainer
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
@@ -19,6 +21,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
gitea_context "code.gitea.io/gitea/services/context"
|
||||
files_service "code.gitea.io/gitea/services/repository/files"
|
||||
"github.com/docker/docker/api/types"
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
@@ -501,15 +504,62 @@ func GetTerminalCommand(ctx context.Context, userID string, repo *repo.Repositor
|
||||
return "", "", err
|
||||
}
|
||||
if status == "running" {
|
||||
//添加脚本文件
|
||||
if setting.K8sConfig.Enable {
|
||||
|
||||
} else {
|
||||
|
||||
var scriptContent []byte
|
||||
_, err = os.Stat("webTerminal.sh")
|
||||
if os.IsNotExist(err) {
|
||||
_, err = os.Stat("/app/gitea/webTerminal.sh")
|
||||
if os.IsNotExist(err) {
|
||||
return "", "", err
|
||||
} else {
|
||||
scriptContent, err = os.ReadFile("/app/gitea/webTerminal.sh")
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scriptContent, err = os.ReadFile("webTerminal.sh")
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
}
|
||||
// 创建 tar 归档文件
|
||||
var buf bytes.Buffer
|
||||
tw := tar.NewWriter(&buf)
|
||||
defer tw.Close()
|
||||
|
||||
// 添加文件到 tar 归档
|
||||
AddFileToTar(tw, "webTerminal.sh", string(scriptContent), 0777)
|
||||
// 创建 Docker 客户端
|
||||
cli, err := docker_module.CreateDockerClient(ctx)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
// 获取容器 ID
|
||||
containerID, err := docker_module.GetContainerID(cli, devContainerInfo.Name)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
err = cli.CopyToContainer(ctx, containerID, "/home", bytes.NewReader(buf.Bytes()), types.CopyToContainerOptions{})
|
||||
if err != nil {
|
||||
log.Info("%v", err)
|
||||
return "", "", err
|
||||
}
|
||||
}
|
||||
realTimeStatus = 3
|
||||
}
|
||||
}
|
||||
break
|
||||
case 3:
|
||||
//正在创建容器,创建容器成功,则状态转移
|
||||
//正在初始化容器,初始化容器成功,则状态转移
|
||||
if setting.K8sConfig.Enable {
|
||||
//k8s的逻辑
|
||||
} else {
|
||||
|
||||
status, err := CheckDirExistsFromDocker(ctx, devContainerInfo.Name, devContainerInfo.DevcontainerWorkDir)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
@@ -520,7 +570,7 @@ func GetTerminalCommand(ctx context.Context, userID string, repo *repo.Repositor
|
||||
}
|
||||
break
|
||||
case 4:
|
||||
//正在创建容器,创建容器成功,则状态转移
|
||||
//正在连接容器
|
||||
if setting.K8sConfig.Enable {
|
||||
//k8s的逻辑
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package devcontainer
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -210,3 +211,19 @@ func ReplacePortOfUrl(originalURL, targetPort string) (string, error) {
|
||||
newURL := parsedURL.String()
|
||||
return newURL, nil
|
||||
}
|
||||
|
||||
// addFileToTar 将文件添加到 tar 归档
|
||||
func AddFileToTar(tw *tar.Writer, filename string, content string, mode int64) error {
|
||||
hdr := &tar.Header{
|
||||
Name: filename,
|
||||
Mode: mode,
|
||||
Size: int64(len(content)),
|
||||
}
|
||||
if err := tw.WriteHeader(hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tw.Write([]byte(content)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -239,13 +239,23 @@ func CreateDevContainerByDockerCommand(ctx context.Context, newDevcontainer *dev
|
||||
log.Info("Failed to insert record: %v", err)
|
||||
return err
|
||||
}
|
||||
cfg, err := setting.NewConfigProviderFromFile(setting.CustomConf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//创建并运行容器的命令
|
||||
if _, err := dbEngine.Table("devcontainer_output").Insert(&devcontainer_models.DevcontainerOutput{
|
||||
Output: "",
|
||||
Status: "waitting",
|
||||
UserId: newDevcontainer.UserId,
|
||||
RepoId: newDevcontainer.RepoId,
|
||||
Command: `docker -H ` + dockerSocket + ` run -d --name ` + newDevcontainer.Name + ` -p 22 ` + imageName + ` sh -c "tail -f /dev/null"` + "\n",
|
||||
Output: "",
|
||||
Status: "waitting",
|
||||
UserId: newDevcontainer.UserId,
|
||||
RepoId: newDevcontainer.RepoId,
|
||||
Command: `docker -H ` + dockerSocket + ` run -d --name ` + newDevcontainer.Name +
|
||||
` -p 22 ` +
|
||||
` -e RepoLink="` + strings.TrimSuffix(cfg.Section("server").Key("ROOT_URL").Value(), `/`) + repo.Link() + `" ` +
|
||||
` -e WorkSpace="` + newDevcontainer.DevcontainerWorkDir + `/` + repo.Name + `"` +
|
||||
` -e PublicKeyList="` + strings.Join(publicKeyList, "\n") + `" ` +
|
||||
imageName +
|
||||
` sh -c "tail -f /dev/null"` + "\n",
|
||||
ListId: 2,
|
||||
DevcontainerId: newDevcontainer.Id,
|
||||
}); err != nil {
|
||||
@@ -258,7 +268,7 @@ func CreateDevContainerByDockerCommand(ctx context.Context, newDevcontainer *dev
|
||||
Status: "waitting",
|
||||
UserId: newDevcontainer.UserId,
|
||||
RepoId: newDevcontainer.RepoId,
|
||||
Command: `docker -H ` + dockerSocket + ` exec ` + newDevcontainer.Name + ` sh -c "echo \"` + newDevcontainer.DevcontainerHost + ` host.docker.internal\" | tee -a /etc/hosts;apt update;apt install -y git ;git clone ` + strings.TrimSuffix(setting.AppURL, "/") + repo.Link() + " /data/workspace/" + repo.Name + `; apt install -y ssh;echo -e "PubkeyAuthentication yes\nPermitRootLogin yes\n" | tee -a /etc/ssh/sshd_config;rm -f /etc/ssh/ssh_host_*; ssh-keygen -A; service ssh restart;mkdir -p ~/.ssh;chmod 700 ~/.ssh;echo "` + strings.Join(publicKeyList, "\n") + `" > ~/.ssh/authorized_keys;chmod 600 ~/.ssh/authorized_keys"` + "\n",
|
||||
Command: `docker -H ` + dockerSocket + ` exec ` + newDevcontainer.Name + ` /home/webTerminal.sh start` + "\n",
|
||||
ListId: 3,
|
||||
DevcontainerId: newDevcontainer.Id,
|
||||
}); err != nil {
|
||||
@@ -552,7 +562,7 @@ func RegistWebTerminal(ctx context.Context) error {
|
||||
containerName := "webterminal-" + timestamp
|
||||
//创建并启动WebTerminal容器
|
||||
err = docker_module.CreateAndStartContainer(ctx, cli, setting.DevContainerConfig.Web_Terminal_Image,
|
||||
[]string{"sh", "-c", "/home/webTerminal/build/ttyd -W bash\n"},
|
||||
nil,
|
||||
nil, binds,
|
||||
nat.PortSet{
|
||||
"7681/tcp": struct{}{},
|
||||
|
||||
@@ -431,4 +431,4 @@
|
||||
</html>
|
||||
<!-- footer end -->
|
||||
|
||||
{{template "repo/devcontainer/devstar-home-vscode-js" .}}
|
||||
{{template "repo/devcontainer/vscode-home-js" .}}
|
||||
70
webTerminal.sh
Normal file
70
webTerminal.sh
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/bin/bash
|
||||
# 获取参数
|
||||
ACTION=$1
|
||||
OS_ID=$(grep '^ID=' /etc/os-release | cut -d= -f2 | tr -d '"')
|
||||
|
||||
|
||||
|
||||
# 根据参数执行不同命令
|
||||
case $ACTION in
|
||||
"start")
|
||||
echo "Starting service..."
|
||||
# 启动服务的命令
|
||||
echo "newDevcontainer.DevcontainerHost host.docker.internal" | tee -a /etc/hosts;
|
||||
case $OS_ID in
|
||||
ubuntu|debian)
|
||||
apt-get update -y
|
||||
apt-get install ssh git -y
|
||||
;;
|
||||
centos)
|
||||
# sudo yum update -y
|
||||
# sudo yum install -y epel-release
|
||||
# sudo yum groupinstall -y "Development Tools"
|
||||
# sudo yum install -y yaml-cpp yaml-cpp-devel
|
||||
;;
|
||||
fedora)
|
||||
# sudo dnf update -y
|
||||
# sudo dnf group install -y "Development Tools"
|
||||
# sudo dnf install -y yaml-cpp yaml-cpp-devel
|
||||
;;
|
||||
*)
|
||||
failure "Unsupported OS: $OS_ID"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo -e "PubkeyAuthentication yes\nPermitRootLogin yes\n" | tee -a /etc/ssh/sshd_config;
|
||||
rm -f /etc/ssh/ssh_host_*;
|
||||
ssh-keygen -A;
|
||||
mkdir -p ~/.ssh;
|
||||
chmod 700 ~/.ssh;
|
||||
case $OS_ID in
|
||||
ubuntu|debian)
|
||||
service ssh restart;
|
||||
;;
|
||||
centos)
|
||||
;;
|
||||
fedora)
|
||||
;;
|
||||
*)
|
||||
failure "Unsupported OS: $OS_ID"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
echo "$PublicKeyList" > ~/.ssh/authorized_keys;
|
||||
chmod 600 ~/.ssh/authorized_keys
|
||||
git clone $RepoLink $WorkSpace
|
||||
;;
|
||||
"stop")
|
||||
echo "Stopping service..."
|
||||
# 停止服务的命令
|
||||
;;
|
||||
"restart")
|
||||
echo "Restarting service..."
|
||||
# 重启服务的命令
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user