mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-12-18 21:38:57 +08:00
fix: Fix the issue of extremely slow container list retrieval (#11142)
Refs #11129
This commit is contained in:
parent
d4edf2f874
commit
f63658db9e
17 changed files with 79 additions and 12 deletions
|
|
@ -263,6 +263,21 @@ func (b *BaseApi) ContainerListStats(c *gin.Context) {
|
||||||
helper.SuccessWithData(c, data)
|
helper.SuccessWithData(c, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary Load container stats size
|
||||||
|
// @Success 200 {object} dto.ContainerItemStats
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Security Timestamp
|
||||||
|
// @Router /containers/item/stats/:id [get]
|
||||||
|
func (b *BaseApi) ContainerItemStats(c *gin.Context) {
|
||||||
|
containerID := c.Param("id")
|
||||||
|
data, err := containerService.ContainerItemStats(containerID)
|
||||||
|
if err != nil {
|
||||||
|
helper.InternalServer(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
// @Tags Container
|
// @Tags Container
|
||||||
// @Summary Create container
|
// @Summary Create container
|
||||||
// @Accept json
|
// @Accept json
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,6 @@ type ContainerInfo struct {
|
||||||
Network []string `json:"network"`
|
Network []string `json:"network"`
|
||||||
Ports []string `json:"ports"`
|
Ports []string `json:"ports"`
|
||||||
|
|
||||||
SizeRw int64 `json:"sizeRw"`
|
|
||||||
SizeRootFs int64 `json:"sizeRootFs"`
|
|
||||||
|
|
||||||
IsFromApp bool `json:"isFromApp"`
|
IsFromApp bool `json:"isFromApp"`
|
||||||
IsFromCompose bool `json:"isFromCompose"`
|
IsFromCompose bool `json:"isFromCompose"`
|
||||||
|
|
||||||
|
|
@ -129,6 +126,10 @@ type ContainerUpgrade struct {
|
||||||
ForcePull bool `json:"forcePull"`
|
ForcePull bool `json:"forcePull"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ContainerItemStats struct {
|
||||||
|
SizeRw int64 `json:"sizeRw"`
|
||||||
|
SizeRootFs int64 `json:"sizeRootFs"`
|
||||||
|
}
|
||||||
type ContainerListStats struct {
|
type ContainerListStats struct {
|
||||||
ContainerID string `json:"containerID"`
|
ContainerID string `json:"containerID"`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ type IContainerService interface {
|
||||||
ContainerUpgrade(req dto.ContainerUpgrade) error
|
ContainerUpgrade(req dto.ContainerUpgrade) error
|
||||||
ContainerInfo(req dto.OperationWithName) (*dto.ContainerOperate, error)
|
ContainerInfo(req dto.OperationWithName) (*dto.ContainerOperate, error)
|
||||||
ContainerListStats() ([]dto.ContainerListStats, error)
|
ContainerListStats() ([]dto.ContainerListStats, error)
|
||||||
|
ContainerItemStats(containerID string) (dto.ContainerItemStats, error)
|
||||||
LoadResourceLimit() (*dto.ResourceLimit, error)
|
LoadResourceLimit() (*dto.ResourceLimit, error)
|
||||||
ContainerRename(req dto.ContainerRename) error
|
ContainerRename(req dto.ContainerRename) error
|
||||||
ContainerCommit(req dto.ContainerCommit) error
|
ContainerCommit(req dto.ContainerCommit) error
|
||||||
|
|
@ -101,10 +102,7 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro
|
||||||
return 0, nil, err
|
return 0, nil, err
|
||||||
}
|
}
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
options := container.ListOptions{
|
options := container.ListOptions{All: true}
|
||||||
All: true,
|
|
||||||
Size: true,
|
|
||||||
}
|
|
||||||
if len(req.Filters) != 0 {
|
if len(req.Filters) != 0 {
|
||||||
options.Filters = filters.NewArgs()
|
options.Filters = filters.NewArgs()
|
||||||
options.Filters.Add("label", req.Filters)
|
options.Filters.Add("label", req.Filters)
|
||||||
|
|
@ -259,6 +257,21 @@ func (u *ContainerService) LoadStatus() (dto.ContainerStatus, error) {
|
||||||
}
|
}
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
func (u *ContainerService) ContainerItemStats(containerID string) (dto.ContainerItemStats, error) {
|
||||||
|
var data dto.ContainerItemStats
|
||||||
|
client, err := docker.NewDockerClient()
|
||||||
|
if err != nil {
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
defer client.Close()
|
||||||
|
containerInfo, _, err := client.ContainerInspectWithRaw(context.Background(), containerID, true)
|
||||||
|
if err != nil {
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
data.SizeRw = *containerInfo.SizeRw
|
||||||
|
data.SizeRootFs = *containerInfo.SizeRootFs
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
func (u *ContainerService) ContainerListStats() ([]dto.ContainerListStats, error) {
|
func (u *ContainerService) ContainerListStats() ([]dto.ContainerListStats, error) {
|
||||||
client, err := docker.NewDockerClient()
|
client, err := docker.NewDockerClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1760,8 +1773,6 @@ func searchWithFilter(req dto.PageContainer, containers []container.Summary) []d
|
||||||
ImageName: item.Image,
|
ImageName: item.Image,
|
||||||
State: item.State,
|
State: item.State,
|
||||||
RunTime: item.Status,
|
RunTime: item.Status,
|
||||||
SizeRw: item.SizeRw,
|
|
||||||
SizeRootFs: item.SizeRootFs,
|
|
||||||
IsFromApp: IsFromApp,
|
IsFromApp: IsFromApp,
|
||||||
IsFromCompose: IsFromCompose,
|
IsFromCompose: IsFromCompose,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ func (s *ContainerRouter) InitRouter(Router *gin.RouterGroup) {
|
||||||
baRouter.POST("/list/byimage", baseApi.ListContainerByImage)
|
baRouter.POST("/list/byimage", baseApi.ListContainerByImage)
|
||||||
baRouter.GET("/status", baseApi.LoadContainerStatus)
|
baRouter.GET("/status", baseApi.LoadContainerStatus)
|
||||||
baRouter.GET("/list/stats", baseApi.ContainerListStats)
|
baRouter.GET("/list/stats", baseApi.ContainerListStats)
|
||||||
|
baRouter.GET("/item/stats/:id", baseApi.ContainerItemStats)
|
||||||
baRouter.GET("/search/log", baseApi.ContainerStreamLogs)
|
baRouter.GET("/search/log", baseApi.ContainerStreamLogs)
|
||||||
baRouter.POST("/download/log", baseApi.DownloadContainerLogs)
|
baRouter.POST("/download/log", baseApi.DownloadContainerLogs)
|
||||||
baRouter.GET("/limit", baseApi.LoadResourceLimit)
|
baRouter.GET("/limit", baseApi.LoadResourceLimit)
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,10 @@ export namespace Container {
|
||||||
name: string;
|
name: string;
|
||||||
state: string;
|
state: string;
|
||||||
}
|
}
|
||||||
|
export interface ContainerItemStats {
|
||||||
|
sizeRw: number;
|
||||||
|
sizeRootFs: number;
|
||||||
|
}
|
||||||
export interface ContainerListStats {
|
export interface ContainerListStats {
|
||||||
containerID: string;
|
containerID: string;
|
||||||
cpuTotalUsage: number;
|
cpuTotalUsage: number;
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,9 @@ export const cleanContainerLog = (containerName: string, operateNode?: string) =
|
||||||
const params = operateNode ? `?operateNode=${operateNode}` : '';
|
const params = operateNode ? `?operateNode=${operateNode}` : '';
|
||||||
return http.post(`/containers/clean/log${params}`, { name: containerName });
|
return http.post(`/containers/clean/log${params}`, { name: containerName });
|
||||||
};
|
};
|
||||||
|
export const containerItemStats = (containerID: string) => {
|
||||||
|
return http.get<Container.ContainerItemStats>(`/containers/item/stats/${containerID}`);
|
||||||
|
};
|
||||||
export const containerListStats = () => {
|
export const containerListStats = () => {
|
||||||
return http.get<Array<Container.ContainerListStats>>(`/containers/list/stats`);
|
return http.get<Array<Container.ContainerListStats>>(`/containers/list/stats`);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -823,6 +823,7 @@ const message = {
|
||||||
memUsage: 'Memory usage',
|
memUsage: 'Memory usage',
|
||||||
memTotal: 'Memory limit',
|
memTotal: 'Memory limit',
|
||||||
memCache: 'Memory cache',
|
memCache: 'Memory cache',
|
||||||
|
loadSize: 'Get Container Size',
|
||||||
ip: 'IP address',
|
ip: 'IP address',
|
||||||
cpuShare: 'CPU shares',
|
cpuShare: 'CPU shares',
|
||||||
cpuShareHelper:
|
cpuShareHelper:
|
||||||
|
|
|
||||||
|
|
@ -826,6 +826,7 @@ const message = {
|
||||||
memUsage: 'Uso de memoria',
|
memUsage: 'Uso de memoria',
|
||||||
memTotal: 'Límite de memoria',
|
memTotal: 'Límite de memoria',
|
||||||
memCache: 'Caché de memoria',
|
memCache: 'Caché de memoria',
|
||||||
|
loadSize: 'Obtener Tamaño del Contenedor',
|
||||||
ip: 'Dirección IP',
|
ip: 'Dirección IP',
|
||||||
cpuShare: 'Proporción de CPU',
|
cpuShare: 'Proporción de CPU',
|
||||||
cpuShareHelper:
|
cpuShareHelper:
|
||||||
|
|
|
||||||
|
|
@ -803,6 +803,7 @@ const message = {
|
||||||
memUsage: 'メモリの使用',
|
memUsage: 'メモリの使用',
|
||||||
memTotal: 'メモリ制限',
|
memTotal: 'メモリ制限',
|
||||||
memCache: 'メモリキャッシュ',
|
memCache: 'メモリキャッシュ',
|
||||||
|
loadSize: 'コンテナサイズを取得',
|
||||||
ip: 'IPアドレス',
|
ip: 'IPアドレス',
|
||||||
cpuShare: 'CPU共有',
|
cpuShare: 'CPU共有',
|
||||||
cpuShareHelper:
|
cpuShareHelper:
|
||||||
|
|
|
||||||
|
|
@ -796,6 +796,7 @@ const message = {
|
||||||
memUsage: '메모리 사용',
|
memUsage: '메모리 사용',
|
||||||
memTotal: '메모리 한도',
|
memTotal: '메모리 한도',
|
||||||
memCache: '메모리 캐시',
|
memCache: '메모리 캐시',
|
||||||
|
loadSize: '컨테이너 크기 가져오기',
|
||||||
ip: 'IP 주소',
|
ip: 'IP 주소',
|
||||||
cpuShare: 'CPU 공유',
|
cpuShare: 'CPU 공유',
|
||||||
cpuShareHelper:
|
cpuShareHelper:
|
||||||
|
|
|
||||||
|
|
@ -816,6 +816,7 @@ const message = {
|
||||||
memUsage: 'Penggunaan memori',
|
memUsage: 'Penggunaan memori',
|
||||||
memTotal: 'Had memori',
|
memTotal: 'Had memori',
|
||||||
memCache: 'Cache memori',
|
memCache: 'Cache memori',
|
||||||
|
loadSize: 'Dapatkan Saiz Bekas',
|
||||||
ip: 'Alamat IP',
|
ip: 'Alamat IP',
|
||||||
cpuShare: 'Bahagian CPU',
|
cpuShare: 'Bahagian CPU',
|
||||||
cpuShareHelper:
|
cpuShareHelper:
|
||||||
|
|
|
||||||
|
|
@ -814,6 +814,7 @@ const message = {
|
||||||
memUsage: 'Uso de memória',
|
memUsage: 'Uso de memória',
|
||||||
memTotal: 'Limite de memória',
|
memTotal: 'Limite de memória',
|
||||||
memCache: 'Cache de memória',
|
memCache: 'Cache de memória',
|
||||||
|
loadSize: 'Obter Tamanho do Contêiner',
|
||||||
ip: 'Endereço IP',
|
ip: 'Endereço IP',
|
||||||
cpuShare: 'Atribuição de CPU',
|
cpuShare: 'Atribuição de CPU',
|
||||||
cpuShareHelper:
|
cpuShareHelper:
|
||||||
|
|
|
||||||
|
|
@ -812,6 +812,7 @@ const message = {
|
||||||
memUsage: 'Использование памяти',
|
memUsage: 'Использование памяти',
|
||||||
memTotal: 'Лимит памяти',
|
memTotal: 'Лимит памяти',
|
||||||
memCache: 'Кэш памяти',
|
memCache: 'Кэш памяти',
|
||||||
|
loadSize: 'Получить Размер Контейнера',
|
||||||
ip: 'IP-адрес',
|
ip: 'IP-адрес',
|
||||||
cpuShare: 'Доли CPU',
|
cpuShare: 'Доли CPU',
|
||||||
cpuShareHelper:
|
cpuShareHelper:
|
||||||
|
|
|
||||||
|
|
@ -832,6 +832,7 @@ const message = {
|
||||||
memUsage: 'Bellek kullanımı',
|
memUsage: 'Bellek kullanımı',
|
||||||
memTotal: 'Bellek sınırı',
|
memTotal: 'Bellek sınırı',
|
||||||
memCache: 'Bellek önbelleği',
|
memCache: 'Bellek önbelleği',
|
||||||
|
loadSize: 'Konteyner Boyutunu Al',
|
||||||
ip: 'IP adresi',
|
ip: 'IP adresi',
|
||||||
cpuShare: 'CPU paylaşımları',
|
cpuShare: 'CPU paylaşımları',
|
||||||
cpuShareHelper:
|
cpuShareHelper:
|
||||||
|
|
|
||||||
|
|
@ -788,6 +788,7 @@ const message = {
|
||||||
memUsage: '記憶體使用',
|
memUsage: '記憶體使用',
|
||||||
memTotal: '記憶體限額',
|
memTotal: '記憶體限額',
|
||||||
memCache: '快取使用',
|
memCache: '快取使用',
|
||||||
|
loadSize: '取得容器大小',
|
||||||
ip: 'IP 位址',
|
ip: 'IP 位址',
|
||||||
cpuShare: 'CPU 權重',
|
cpuShare: 'CPU 權重',
|
||||||
cpuShareHelper: '容器預設份額為 1024 個 CPU,增大可使目前容器獲得更多的 CPU 時間',
|
cpuShareHelper: '容器預設份額為 1024 個 CPU,增大可使目前容器獲得更多的 CPU 時間',
|
||||||
|
|
|
||||||
|
|
@ -789,6 +789,7 @@ const message = {
|
||||||
memUsage: '内存使用',
|
memUsage: '内存使用',
|
||||||
memTotal: '内存限额',
|
memTotal: '内存限额',
|
||||||
memCache: '缓存使用',
|
memCache: '缓存使用',
|
||||||
|
loadSize: '获取容器大小',
|
||||||
ip: 'IP 地址',
|
ip: 'IP 地址',
|
||||||
cpuShare: 'CPU 权重',
|
cpuShare: 'CPU 权重',
|
||||||
cpuShareHelper: '容器默认份额为 1024 个 CPU,增大可使当前容器获得更多的 CPU 时间',
|
cpuShareHelper: '容器默认份额为 1024 个 CPU,增大可使当前容器获得更多的 CPU 时间',
|
||||||
|
|
|
||||||
|
|
@ -209,8 +209,7 @@
|
||||||
<el-descriptions-item :label="$t('container.memTotal')">
|
<el-descriptions-item :label="$t('container.memTotal')">
|
||||||
{{ computeSizeForDocker(row.memoryLimit) }}
|
{{ computeSizeForDocker(row.memoryLimit) }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item v-if="row.hasLoadSize">
|
||||||
<el-descriptions-item>
|
|
||||||
<template #label>
|
<template #label>
|
||||||
{{ $t('container.sizeRw') }}
|
{{ $t('container.sizeRw') }}
|
||||||
<el-tooltip :content="$t('container.sizeRwHelper')">
|
<el-tooltip :content="$t('container.sizeRwHelper')">
|
||||||
|
|
@ -219,7 +218,10 @@
|
||||||
</template>
|
</template>
|
||||||
{{ computeSize2(row.sizeRw) }}
|
{{ computeSize2(row.sizeRw) }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item :label="$t('container.sizeRootFs')">
|
<el-descriptions-item
|
||||||
|
:label="$t('container.sizeRootFs')"
|
||||||
|
v-if="row.hasLoadSize"
|
||||||
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
{{ $t('container.sizeRootFs') }}
|
{{ $t('container.sizeRootFs') }}
|
||||||
<el-tooltip :content="$t('container.sizeRootFsHelper')">
|
<el-tooltip :content="$t('container.sizeRootFsHelper')">
|
||||||
|
|
@ -229,6 +231,17 @@
|
||||||
{{ computeSize2(row.sizeRootFs) }}
|
{{ computeSize2(row.sizeRootFs) }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
class="mt-2"
|
||||||
|
v-if="!row.hasLoadSize"
|
||||||
|
size="small"
|
||||||
|
link
|
||||||
|
type="primary"
|
||||||
|
@click="loadSize(row)"
|
||||||
|
>
|
||||||
|
{{ $t('container.loadSize') }}
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -384,6 +397,7 @@ import ContainerLogDialog from '@/components/log/container-drawer/index.vue';
|
||||||
import Status from '@/components/status/index.vue';
|
import Status from '@/components/status/index.vue';
|
||||||
import { reactive, onMounted, ref, computed } from 'vue';
|
import { reactive, onMounted, ref, computed } from 'vue';
|
||||||
import {
|
import {
|
||||||
|
containerItemStats,
|
||||||
containerListStats,
|
containerListStats,
|
||||||
containerOperator,
|
containerOperator,
|
||||||
inspect,
|
inspect,
|
||||||
|
|
@ -588,6 +602,14 @@ const refresh = async () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const loadSize = async (row: any) => {
|
||||||
|
containerItemStats(row.containerID).then((res) => {
|
||||||
|
row.sizeRw = res.data.sizeRw || 0;
|
||||||
|
row.sizeRootFs = res.data.sizeRootFs || 0;
|
||||||
|
row.hasLoadSize = true;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const loadStats = async () => {
|
const loadStats = async () => {
|
||||||
const res = await containerListStats();
|
const res = await containerListStats();
|
||||||
let stats = res.data || [];
|
let stats = res.data || [];
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue