feat: Adding GPU acceleration configuration to some applications (#7865)

This commit is contained in:
zhengkunwang 2025-02-13 15:02:08 +08:00 committed by GitHub
parent 1c199bd3d7
commit f233ef7069
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 64 additions and 12 deletions

View file

@ -90,6 +90,7 @@ type AppProperty struct {
Github string `json:"github"` Github string `json:"github"`
Document string `json:"document"` Document string `json:"document"`
Version float64 `json:"version"` Version float64 `json:"version"`
GpuSupport bool `json:"gpuSupport"`
} }
type AppConfigVersion struct { type AppConfigVersion struct {

View file

@ -33,6 +33,7 @@ type AppContainerConfig struct {
DockerCompose string `json:"dockerCompose"` DockerCompose string `json:"dockerCompose"`
HostMode bool `json:"hostMode"` HostMode bool `json:"hostMode"`
PullImage bool `json:"pullImage"` PullImage bool `json:"pullImage"`
GpuConfig bool `json:"gpuConfig"`
} }
type AppInstalledSearch struct { type AppInstalledSearch struct {

View file

@ -41,6 +41,7 @@ type AppItem struct {
Versions []string `json:"versions"` Versions []string `json:"versions"`
Limit int `json:"limit"` Limit int `json:"limit"`
Tags []TagDTO `json:"tags"` Tags []TagDTO `json:"tags"`
GpuSupport bool `json:"gpuSupport"`
} }
type TagDTO struct { type TagDTO struct {
@ -66,10 +67,11 @@ type AppInstalledCheck struct {
type AppDetailDTO struct { type AppDetailDTO struct {
model.AppDetail model.AppDetail
Enable bool `json:"enable"` Enable bool `json:"enable"`
Params interface{} `json:"params"` Params interface{} `json:"params"`
Image string `json:"image"` Image string `json:"image"`
HostMode bool `json:"hostMode"` HostMode bool `json:"hostMode"`
GpuSupport bool `json:"gpuSupport"`
} }
type IgnoredApp struct { type IgnoredApp struct {

View file

@ -20,6 +20,7 @@ type App struct {
Type string `json:"type" gorm:"type:varchar(64);not null"` Type string `json:"type" gorm:"type:varchar(64);not null"`
Status string `json:"status" gorm:"type:varchar(64);not null"` Status string `json:"status" gorm:"type:varchar(64);not null"`
Required string `json:"required" gorm:"type:varchar(64);"` Required string `json:"required" gorm:"type:varchar(64);"`
GpuSupport bool `json:"gpuSupport"`
CrossVersionUpdate bool `json:"crossVersionUpdate" yaml:"crossVersionUpdate"` CrossVersionUpdate bool `json:"crossVersionUpdate" yaml:"crossVersionUpdate"`
Limit int `json:"limit" gorm:"type:Integer;not null"` Limit int `json:"limit" gorm:"type:Integer;not null"`
Website string `json:"website" gorm:"type:varchar(64);not null"` Website string `json:"website" gorm:"type:varchar(64);not null"`

View file

@ -94,13 +94,14 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{
lang := strings.ToLower(common.GetLang(ctx)) lang := strings.ToLower(common.GetLang(ctx))
for _, ap := range apps { for _, ap := range apps {
appDTO := &response.AppItem{ appDTO := &response.AppItem{
ID: ap.ID, ID: ap.ID,
Name: ap.Name, Name: ap.Name,
Key: ap.Key, Key: ap.Key,
Type: ap.Type, Type: ap.Type,
Icon: ap.Icon, Icon: ap.Icon,
Resource: ap.Resource, Resource: ap.Resource,
Limit: ap.Limit, Limit: ap.Limit,
GpuSupport: ap.GpuSupport,
} }
appDTO.Description = ap.GetDescription(ctx) appDTO.Description = ap.GetDescription(ctx)
appDTOs = append(appDTOs, appDTO) appDTOs = append(appDTOs, appDTO)
@ -167,6 +168,7 @@ func (a AppService) GetApp(ctx *gin.Context, key string) (*response.AppDTO, erro
if err != nil { if err != nil {
return nil, err return nil, err
} }
appDTO.GpuSupport = app.GpuSupport
appDTO.Tags = tags appDTO.Tags = tags
return &appDTO, nil return &appDTO, nil
} }
@ -264,6 +266,7 @@ func (a AppService) GetAppDetail(appID uint, version, appType string) (response.
if err := checkLimit(app); err != nil { if err := checkLimit(app); err != nil {
appDetailDTO.Enable = false appDetailDTO.Enable = false
} }
appDetailDTO.GpuSupport = app.GpuSupport
return appDetailDTO, nil return appDetailDTO, nil
} }
func (a AppService) GetAppDetailByID(id uint) (*response.AppDetailDTO, error) { func (a AppService) GetAppDetailByID(id uint) (*response.AppDetailDTO, error) {
@ -862,6 +865,7 @@ func (a AppService) SyncAppListFromRemote() (err error) {
global.LOG.Infof("Starting synchronization of application details...") global.LOG.Infof("Starting synchronization of application details...")
for _, l := range list.Apps { for _, l := range list.Apps {
app := appsMap[l.AppProperty.Key] app := appsMap[l.AppProperty.Key]
app.GpuSupport = l.AppProperty.GpuSupport
if l.AppProperty.Version > 0 && common.CompareVersion(strconv.FormatFloat(l.AppProperty.Version, 'f', -1, 64), setting.SystemVersion) { if l.AppProperty.Version > 0 && common.CompareVersion(strconv.FormatFloat(l.AppProperty.Version, 'f', -1, 64), setting.SystemVersion) {
delete(appsMap, l.AppProperty.Key) delete(appsMap, l.AppProperty.Key)

View file

@ -1500,6 +1500,18 @@ func addDockerComposeCommonParam(composeMap map[string]interface{}, serviceName
deploy["resources"] = resource deploy["resources"] = resource
serviceValue["deploy"] = deploy serviceValue["deploy"] = deploy
if req.GpuConfig {
resource["reservations"] = map[string]interface{}{
"devices": []map[string]interface{}{
{
"driver": "nvidia",
"count": "all",
"capabilities": []string{"gpu"},
},
},
}
}
ports, ok := serviceValue["ports"].([]interface{}) ports, ok := serviceValue["ports"].([]interface{})
if ok { if ok {
for i, port := range ports { for i, port := range ports {

View file

@ -372,7 +372,7 @@ var UpdateAppTag = &gormigrate.Migration{
} }
var UpdateApp = &gormigrate.Migration{ var UpdateApp = &gormigrate.Migration{
ID: "20250114-update-app", ID: "20250213-update-app",
Migrate: func(tx *gorm.DB) error { Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.App{}); err != nil { if err := tx.AutoMigrate(&model.App{}); err != nil {
return err return err

View file

@ -14,6 +14,7 @@ export namespace App {
type: string; type: string;
status: string; status: string;
limit: number; limit: number;
gpuSupport: boolean;
} }
export interface AppDTO extends App { export interface AppDTO extends App {
@ -46,6 +47,7 @@ export namespace App {
dockerCompose: string; dockerCompose: string;
image: string; image: string;
hostMode?: boolean; hostMode?: boolean;
gpuSupport: boolean;
} }
export interface AppReq extends ReqPage { export interface AppReq extends ReqPage {

View file

@ -1927,6 +1927,9 @@ const message = {
'The left side is the old version, the right side is the new version. After editing, click to save the custom version', 'The left side is the old version, the right side is the new version. After editing, click to save the custom version',
pullImage: 'Pull Image', pullImage: 'Pull Image',
pullImageHelper: 'Execute docker pull to pull the image before the application starts', pullImageHelper: 'Execute docker pull to pull the image before the application starts',
gpuConfig: 'GPU Acceleration',
gpuConfigHelper:
'Please ensure the machine has an NVIDIA GPU and that NVIDIA drivers and the NVIDIA Docker Container Toolkit are installed',
}, },
website: { website: {
website: 'Website | Websites', website: 'Website | Websites',

View file

@ -1900,6 +1900,9 @@ const message = {
'左側は古いバージョンで右側は新しいバージョンです編集後クリックしてカスタムバージョンを保存します', '左側は古いバージョンで右側は新しいバージョンです編集後クリックしてカスタムバージョンを保存します',
pullImage: '画像を引っ張ります', pullImage: '画像を引っ張ります',
pullImageHelper: 'アプリケーションが開始する前にDocker Pullを実行して画像をプルします', pullImageHelper: 'アプリケーションが開始する前にDocker Pullを実行して画像をプルします',
gpuConfig: 'GPU アクセラレーション',
gpuConfigHelper:
'マシンにNVIDIA GPUが搭載されていることを確認しNVIDIAドライバーとNVIDIA Docker Container Toolkitをインストールしてください',
}, },
website: { website: {
website: 'ウェブサイト|ウェブサイト', website: 'ウェブサイト|ウェブサイト',

View file

@ -1869,6 +1869,9 @@ const message = {
diffHelper: '왼쪽은 이전 버전, 오른쪽은 버전입니다. 편집 사용자 정의 버전을 저장하려면 클릭하세요.', diffHelper: '왼쪽은 이전 버전, 오른쪽은 버전입니다. 편집 사용자 정의 버전을 저장하려면 클릭하세요.',
pullImage: '이미지 ', pullImage: '이미지 ',
pullImageHelper: '애플리케이션 시작 전에 docker pull 실행하여 이미지를 다운로드하세요.', pullImageHelper: '애플리케이션 시작 전에 docker pull 실행하여 이미지를 다운로드하세요.',
gpuConfig: 'GPU 가속',
gpuConfigHelper:
'기계에 NVIDIA GPU가 설치되어 있고 NVIDIA 드라이버와 NVIDIA Docker Container Toolkit이 설치되어 있는지 확인하십시오.',
}, },
website: { website: {
website: '웹사이트 | 웹사이트들', website: '웹사이트 | 웹사이트들',

View file

@ -1951,6 +1951,9 @@ const message = {
diffHelper: 'Bahagian kiri ialah versi lama, kanan ialah versi baru.', diffHelper: 'Bahagian kiri ialah versi lama, kanan ialah versi baru.',
pullImage: 'Tarik Imej', pullImage: 'Tarik Imej',
pullImageHelper: 'Laksanakan docker pull untuk menarik imej sebelum aplikasi dimulakan.', pullImageHelper: 'Laksanakan docker pull untuk menarik imej sebelum aplikasi dimulakan.',
gpuConfig: 'Pecutan GPU',
gpuConfigHelper:
'Pastikan mesin mempunyai GPU NVIDIA dan pasang pemacu NVIDIA serta NVIDIA Docker Container Toolkit.',
}, },
website: { website: {
website: 'Laman Web | Laman Web', website: 'Laman Web | Laman Web',

View file

@ -1941,6 +1941,9 @@ const message = {
'O lado esquerdo é a versão antiga, o lado direito é a nova versão. Após editar, clique para salvar a versão personalizada', 'O lado esquerdo é a versão antiga, o lado direito é a nova versão. Após editar, clique para salvar a versão personalizada',
pullImage: 'Puxar Imagem', pullImage: 'Puxar Imagem',
pullImageHelper: 'Execute o comando docker pull para puxar a imagem antes de iniciar o aplicativo', pullImageHelper: 'Execute o comando docker pull para puxar a imagem antes de iniciar o aplicativo',
gpuConfig: 'Aceleração de GPU',
gpuConfigHelper:
'Certifique-se de que a máquina possui uma GPU NVIDIA e instale os drivers NVIDIA e o NVIDIA Docker Container Toolkit.',
}, },
website: { website: {
website: 'Website | Websites', website: 'Website | Websites',

View file

@ -1943,6 +1943,9 @@ const message = {
'Слева старая версия, справа новая версия. После редактирования нажмите для сохранения пользовательской версии', 'Слева старая версия, справа новая версия. После редактирования нажмите для сохранения пользовательской версии',
pullImage: 'Загрузить образ', pullImage: 'Загрузить образ',
pullImageHelper: 'Выполнить docker pull для загрузки образа перед запуском приложения', pullImageHelper: 'Выполнить docker pull для загрузки образа перед запуском приложения',
gpuConfig: 'GPU Hızlandırma',
gpuConfigHelper:
'Пожалуйста, убедитесь, что на машине есть NVIDIA GPU и установлены драйвера NVIDIA и NVIDIA Docker Container Toolkit',
}, },
website: { website: {
website: 'Веб-сайт | Веб-сайты', website: 'Веб-сайт | Веб-сайты',

View file

@ -1802,6 +1802,8 @@ const message = {
diffHelper: '左側為舊版本右側為新版編輯之後點選使用自訂版本儲存', diffHelper: '左側為舊版本右側為新版編輯之後點選使用自訂版本儲存',
pullImage: '拉取鏡像', pullImage: '拉取鏡像',
pullImageHelper: '在應用啟動之前執行 docker pull 來拉取鏡像', pullImageHelper: '在應用啟動之前執行 docker pull 來拉取鏡像',
gpuConfig: 'GPU 加速',
gpuConfigHelper: '請確保機器有 NVIDIA GPU 並且安裝 NVIDIA 驅動程式和 NVIDIA Docker Container Toolkit',
}, },
website: { website: {
website: '網站', website: '網站',

View file

@ -1801,6 +1801,8 @@ const message = {
diffHelper: '左侧为旧版本右侧为新版编辑之后点击使用自定义版本保存', diffHelper: '左侧为旧版本右侧为新版编辑之后点击使用自定义版本保存',
pullImage: '拉取镜像', pullImage: '拉取镜像',
pullImageHelper: '在应用启动之前执行 docker pull 来拉取镜像', pullImageHelper: '在应用启动之前执行 docker pull 来拉取镜像',
gpuConfig: 'GPU 加速',
gpuConfigHelper: '请确保机器有 NVIDIA GPU 并且安装 NVIDIA 驱动 NVIDIA docker Container Toolkit',
}, },
website: { website: {
website: '网站', website: '网站',

View file

@ -108,6 +108,10 @@
<el-checkbox v-model="req.editCompose" :label="$t('app.editCompose')" size="large" /> <el-checkbox v-model="req.editCompose" :label="$t('app.editCompose')" size="large" />
<span class="input-help">{{ $t('app.editComposeHelper') }}</span> <span class="input-help">{{ $t('app.editComposeHelper') }}</span>
</el-form-item> </el-form-item>
<el-form-item pro="gpuConfig" v-if="gpuSupport">
<el-checkbox v-model="req.gpuConfig" :label="$t('app.gpuConfig')" size="large" />
<span class="input-help">{{ $t('app.gpuConfigHelper') }}</span>
</el-form-item>
<el-form-item pro="pullImage"> <el-form-item pro="pullImage">
<el-checkbox v-model="req.pullImage" :label="$t('app.pullImage')" size="large" /> <el-checkbox v-model="req.pullImage" :label="$t('app.pullImage')" size="large" />
<span class="input-help">{{ $t('app.pullImageHelper') }}</span> <span class="input-help">{{ $t('app.pullImageHelper') }}</span>
@ -198,6 +202,7 @@ const initData = () => ({
version: '', version: '',
appID: '', appID: '',
pullImage: true, pullImage: true,
gpuConfig: false,
}); });
const req = reactive(initData()); const req = reactive(initData());
const limits = ref<Container.ResourceLimit>({ const limits = ref<Container.ResourceLimit>({
@ -215,6 +220,7 @@ const handleClose = () => {
}; };
const paramKey = ref(1); const paramKey = ref(1);
const isHostMode = ref(false); const isHostMode = ref(false);
const gpuSupport = ref(false);
const changeUnit = () => { const changeUnit = () => {
if (req.memoryUnit == 'M') { if (req.memoryUnit == 'M') {
@ -262,6 +268,7 @@ const getAppDetail = async (version: string) => {
isHostMode.value = res.data.hostMode; isHostMode.value = res.data.hostMode;
installData.value.params = res.data.params; installData.value.params = res.data.params;
paramKey.value++; paramKey.value++;
gpuSupport.value = res.data.gpuSupport;
} catch (error) { } catch (error) {
} finally { } finally {
loading.value = false; loading.value = false;