mirror of https://github.com/1Panel-dev/1Panel
feat: docker 服务不可用时,设置遮罩
parent
004b997288
commit
9a214885c3
|
@ -2,6 +2,7 @@ package service
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
@ -39,7 +40,12 @@ type daemonJsonItem struct {
|
|||
|
||||
func (u *DockerService) LoadDockerStatus() string {
|
||||
status := constant.StatusRunning
|
||||
if _, err := docker.NewDockerClient(); err != nil {
|
||||
cli, err := docker.NewDockerClient()
|
||||
if err != nil {
|
||||
status = constant.Stopped
|
||||
}
|
||||
pong, err := cli.Ping(context.Background())
|
||||
if !pong.Experimental || err != nil {
|
||||
status = constant.Stopped
|
||||
}
|
||||
return status
|
||||
|
|
|
@ -3,6 +3,7 @@ package service
|
|||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
|
@ -56,8 +57,24 @@ func (u *ImageRepoService) Create(imageRepoDto dto.ImageRepoCreate) error {
|
|||
if imageRepo.ID != 0 {
|
||||
return constant.ErrRecordExist
|
||||
}
|
||||
|
||||
fileSetting, err := settingRepo.Get(settingRepo.WithByKey("DaemonJsonPath"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(fileSetting.Value) == 0 {
|
||||
return errors.New("error daemon.json path in request")
|
||||
}
|
||||
if _, err := os.Stat(fileSetting.Value); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(fileSetting.Value, os.ModePerm); err != nil {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if imageRepoDto.Protocol == "http" {
|
||||
file, err := ioutil.ReadFile(constant.DaemonJsonDir)
|
||||
file, err := ioutil.ReadFile(fileSetting.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -76,7 +93,7 @@ func (u *ImageRepoService) Create(imageRepoDto dto.ImageRepoCreate) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile(constant.DaemonJsonDir, newJson, 0640); err != nil {
|
||||
if err := ioutil.WriteFile(fileSetting.Value, newJson, 0640); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ const (
|
|||
ComposeOpRestart = "restart"
|
||||
ComposeOpRemove = "remove"
|
||||
|
||||
DaemonJsonDir = "/opt/1Panel/docker/conf/daemon.json"
|
||||
TmpDockerBuildDir = "/opt/1Panel/data/docker/build"
|
||||
TmpComposeBuildDir = "/opt/1Panel/data/docker/compose"
|
||||
)
|
||||
|
|
|
@ -130,6 +130,9 @@ export const dockerOperate = (params: Container.DockerOperate) => {
|
|||
export const loadDaemonJson = () => {
|
||||
return http.get<Container.DaemonJsonConf>(`/containers/daemonjson`);
|
||||
};
|
||||
export const loadDockerStatus = () => {
|
||||
return http.get<string>(`/containers/docker/status`);
|
||||
};
|
||||
export const updateDaemonJson = (params: Container.DaemonJsonConf) => {
|
||||
return http.post(`/containers/daemonjson/update`, params);
|
||||
};
|
||||
|
|
|
@ -459,6 +459,8 @@ export default {
|
|||
registries: 'Insecure registries',
|
||||
liveHelper: 'Whether to close all containers when stopping the docker service',
|
||||
daemonJsonPath: 'Conf Path',
|
||||
serviceUnavailable: 'Docker service is not started at present, please click',
|
||||
startIn: ' to start',
|
||||
},
|
||||
cronjob: {
|
||||
cronTask: 'Task',
|
||||
|
|
|
@ -466,6 +466,8 @@ export default {
|
|||
registries: '私有仓库',
|
||||
liveHelper: '停止 docker 服务时,是否关闭所有容器',
|
||||
daemonJsonPath: '配置路径',
|
||||
serviceUnavailable: '当前未启动 Docker 服务,请在',
|
||||
startIn: '中开启',
|
||||
},
|
||||
cronjob: {
|
||||
cronTask: '计划任务',
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
<template>
|
||||
<div v-loading="loading">
|
||||
<Submenu activeName="compose" />
|
||||
<el-card style="margin-top: 20px">
|
||||
<el-card width="30%" v-if="dockerStatus != 'Running'" class="mask-prompt">
|
||||
<span style="font-size: 14px">{{ $t('container.serviceUnavailable') }}</span>
|
||||
<el-button type="primary" link style="font-size: 14px; margin-bottom: 5px" @click="goSetting">
|
||||
【 {{ $t('container.setting') }} 】
|
||||
</el-button>
|
||||
<span style="font-size: 14px">{{ $t('container.startIn') }}</span>
|
||||
</el-card>
|
||||
<el-card style="margin-top: 20px" :class="{ mask: dockerStatus != 'Running' }">
|
||||
<div v-if="!isOnDetail">
|
||||
<ComplexTable
|
||||
:pagination-config="paginationConfig"
|
||||
|
@ -59,12 +66,13 @@ import EditDialog from '@/views/container/compose/edit/index.vue';
|
|||
import CreateDialog from '@/views/container/compose/create/index.vue';
|
||||
import ComposeDetial from '@/views/container/compose/detail/index.vue';
|
||||
import Submenu from '@/views/container/index.vue';
|
||||
import { composeOperator, searchCompose } from '@/api/modules/container';
|
||||
import { composeOperator, loadDockerStatus, searchCompose } from '@/api/modules/container';
|
||||
import i18n from '@/lang';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
import { LoadFile } from '@/api/modules/files';
|
||||
import router from '@/routers';
|
||||
|
||||
const data = ref();
|
||||
const selects = ref<any>([]);
|
||||
|
@ -78,6 +86,18 @@ const paginationConfig = reactive({
|
|||
total: 0,
|
||||
});
|
||||
|
||||
const dockerStatus = ref();
|
||||
const loadStatus = async () => {
|
||||
const res = await loadDockerStatus();
|
||||
dockerStatus.value = res.data;
|
||||
if (dockerStatus.value === 'Running') {
|
||||
search();
|
||||
}
|
||||
};
|
||||
const goSetting = async () => {
|
||||
router.push({ name: 'ContainerSetting' });
|
||||
};
|
||||
|
||||
const search = async () => {
|
||||
let params = {
|
||||
page: paginationConfig.currentPage,
|
||||
|
@ -158,6 +178,6 @@ const buttons = [
|
|||
},
|
||||
];
|
||||
onMounted(() => {
|
||||
search();
|
||||
loadStatus();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
<template>
|
||||
<div>
|
||||
<Submenu activeName="container" />
|
||||
<el-card style="margin-top: 20px">
|
||||
<el-card width="30%" v-if="dockerStatus != 'Running'" class="mask-prompt">
|
||||
<span style="font-size: 14px">{{ $t('container.serviceUnavailable') }}</span>
|
||||
<el-button type="primary" link style="font-size: 14px; margin-bottom: 5px" @click="goSetting">
|
||||
【 {{ $t('container.setting') }} 】
|
||||
</el-button>
|
||||
<span style="font-size: 14px">{{ $t('container.startIn') }}</span>
|
||||
</el-card>
|
||||
<el-card style="margin-top: 20px" :class="{ mask: dockerStatus != 'Running' }">
|
||||
<ComplexTable :pagination-config="paginationConfig" v-model:selects="selects" :data="data" @search="search">
|
||||
<template #toolbar>
|
||||
<el-button icon="Plus" type="primary" @click="onCreate()">
|
||||
|
@ -88,10 +95,11 @@ import CodemirrorDialog from '@/components/codemirror-dialog/codemirror.vue';
|
|||
import Submenu from '@/views/container/index.vue';
|
||||
import { reactive, onMounted, ref } from 'vue';
|
||||
import { dateFromat } from '@/utils/util';
|
||||
import { ContainerOperator, inspect, searchContainer } from '@/api/modules/container';
|
||||
import { ContainerOperator, inspect, loadDockerStatus, searchContainer } from '@/api/modules/container';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import i18n from '@/lang';
|
||||
import router from '@/routers';
|
||||
|
||||
const data = ref();
|
||||
const selects = ref<any>([]);
|
||||
|
@ -101,6 +109,18 @@ const paginationConfig = reactive({
|
|||
total: 0,
|
||||
});
|
||||
|
||||
const dockerStatus = ref();
|
||||
const loadStatus = async () => {
|
||||
const res = await loadDockerStatus();
|
||||
dockerStatus.value = res.data;
|
||||
if (dockerStatus.value === 'Running') {
|
||||
search();
|
||||
}
|
||||
};
|
||||
const goSetting = async () => {
|
||||
router.push({ name: 'ContainerSetting' });
|
||||
};
|
||||
|
||||
interface Filters {
|
||||
filters?: string;
|
||||
}
|
||||
|
@ -251,6 +271,6 @@ const buttons = [
|
|||
];
|
||||
|
||||
onMounted(() => {
|
||||
search();
|
||||
loadStatus();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
<template>
|
||||
<div v-loading="loading">
|
||||
<Submenu activeName="image" />
|
||||
<el-card style="margin-top: 20px">
|
||||
<el-card width="30%" v-if="dockerStatus != 'Running'" class="mask-prompt">
|
||||
<span style="font-size: 14px">{{ $t('container.serviceUnavailable') }}</span>
|
||||
<el-button type="primary" link style="font-size: 14px; margin-bottom: 5px" @click="goSetting">
|
||||
【 {{ $t('container.setting') }} 】
|
||||
</el-button>
|
||||
<span style="font-size: 14px">{{ $t('container.startIn') }}</span>
|
||||
</el-card>
|
||||
<el-card style="margin-top: 20px" :class="{ mask: dockerStatus != 'Running' }">
|
||||
<ComplexTable :pagination-config="paginationConfig" v-model:selects="selects" :data="data" @search="search">
|
||||
<template #toolbar>
|
||||
<el-button @click="onOpenPull">
|
||||
|
@ -89,10 +96,11 @@ import Push from '@/views/container/image/push/index.vue';
|
|||
import Save from '@/views/container/image/save/index.vue';
|
||||
import Load from '@/views/container/image/load/index.vue';
|
||||
import Build from '@/views/container/image/build/index.vue';
|
||||
import { searchImage, listImageRepo, imageRemove } from '@/api/modules/container';
|
||||
import { searchImage, listImageRepo, imageRemove, loadDockerStatus } from '@/api/modules/container';
|
||||
import i18n from '@/lang';
|
||||
import { ElForm } from 'element-plus';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
import router from '@/routers';
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
|
@ -105,6 +113,19 @@ const paginationConfig = reactive({
|
|||
total: 0,
|
||||
});
|
||||
|
||||
const dockerStatus = ref();
|
||||
const loadStatus = async () => {
|
||||
const res = await loadDockerStatus();
|
||||
dockerStatus.value = res.data;
|
||||
if (dockerStatus.value === 'Running') {
|
||||
search();
|
||||
loadRepos();
|
||||
}
|
||||
};
|
||||
const goSetting = async () => {
|
||||
router.push({ name: 'ContainerSetting' });
|
||||
};
|
||||
|
||||
const dialogPullRef = ref();
|
||||
const dialogTagRef = ref();
|
||||
const dialogPushRef = ref();
|
||||
|
@ -206,7 +227,6 @@ const buttons = [
|
|||
];
|
||||
|
||||
onMounted(() => {
|
||||
search();
|
||||
loadRepos();
|
||||
loadStatus();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
<template>
|
||||
<div>
|
||||
<Submenu activeName="network" />
|
||||
<el-card style="margin-top: 20px">
|
||||
<el-card width="30%" v-if="dockerStatus != 'Running'" class="mask-prompt">
|
||||
<span style="font-size: 14px">{{ $t('container.serviceUnavailable') }}</span>
|
||||
<el-button type="primary" link style="font-size: 14px; margin-bottom: 5px" @click="goSetting">
|
||||
【 {{ $t('container.setting') }} 】
|
||||
</el-button>
|
||||
<span style="font-size: 14px">{{ $t('container.startIn') }}</span>
|
||||
</el-card>
|
||||
<el-card style="margin-top: 20px" :class="{ mask: dockerStatus != 'Running' }">
|
||||
<ComplexTable :pagination-config="paginationConfig" v-model:selects="selects" :data="data" @search="search">
|
||||
<template #toolbar>
|
||||
<el-button icon="Plus" type="primary" @click="onCreate()">
|
||||
|
@ -57,10 +64,11 @@ import CodemirrorDialog from '@/components/codemirror-dialog/codemirror.vue';
|
|||
import Submenu from '@/views/container/index.vue';
|
||||
import { reactive, onMounted, ref } from 'vue';
|
||||
import { dateFromat } from '@/utils/util';
|
||||
import { deleteNetwork, searchNetwork, inspect } from '@/api/modules/container';
|
||||
import { deleteNetwork, searchNetwork, inspect, loadDockerStatus } from '@/api/modules/container';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import i18n from '@/lang';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
import router from '@/routers';
|
||||
|
||||
const detailInfo = ref();
|
||||
const codemirror = ref();
|
||||
|
@ -73,6 +81,18 @@ const paginationConfig = reactive({
|
|||
total: 0,
|
||||
});
|
||||
|
||||
const dockerStatus = ref();
|
||||
const loadStatus = async () => {
|
||||
const res = await loadDockerStatus();
|
||||
dockerStatus.value = res.data;
|
||||
if (dockerStatus.value === 'Running') {
|
||||
search();
|
||||
}
|
||||
};
|
||||
const goSetting = async () => {
|
||||
router.push({ name: 'ContainerSetting' });
|
||||
};
|
||||
|
||||
const dialogCreateRef = ref<DialogExpose>();
|
||||
|
||||
interface DialogExpose {
|
||||
|
@ -140,6 +160,6 @@ const buttons = [
|
|||
];
|
||||
|
||||
onMounted(() => {
|
||||
search();
|
||||
loadStatus();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
<template>
|
||||
<div>
|
||||
<Submenu activeName="repo" />
|
||||
<el-card style="margin-top: 20px">
|
||||
<el-card width="30%" v-if="dockerStatus != 'Running'" class="mask-prompt">
|
||||
<span style="font-size: 14px">{{ $t('container.serviceUnavailable') }}</span>
|
||||
<el-button type="primary" link style="font-size: 14px; margin-bottom: 5px" @click="goSetting">
|
||||
【 {{ $t('container.setting') }} 】
|
||||
</el-button>
|
||||
<span style="font-size: 14px">{{ $t('container.startIn') }}</span>
|
||||
</el-card>
|
||||
<el-card style="margin-top: 20px" :class="{ mask: dockerStatus != 'Running' }">
|
||||
<ComplexTable :pagination-config="paginationConfig" v-model:selects="selects" :data="data" @search="search">
|
||||
<template #toolbar>
|
||||
<el-button icon="Plus" type="primary" @click="onOpenDialog('create')">
|
||||
|
@ -40,9 +47,10 @@ import Submenu from '@/views/container/index.vue';
|
|||
import { reactive, onMounted, ref } from 'vue';
|
||||
import { dateFromat } from '@/utils/util';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import { deleteImageRepo, searchImageRepo } from '@/api/modules/container';
|
||||
import { deleteImageRepo, loadDockerStatus, searchImageRepo } from '@/api/modules/container';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
import i18n from '@/lang';
|
||||
import router from '@/routers';
|
||||
|
||||
const data = ref();
|
||||
const selects = ref<any>([]);
|
||||
|
@ -52,6 +60,18 @@ const paginationConfig = reactive({
|
|||
total: 0,
|
||||
});
|
||||
|
||||
const dockerStatus = ref();
|
||||
const loadStatus = async () => {
|
||||
const res = await loadDockerStatus();
|
||||
dockerStatus.value = res.data;
|
||||
if (dockerStatus.value === 'Running') {
|
||||
search();
|
||||
}
|
||||
};
|
||||
const goSetting = async () => {
|
||||
router.push({ name: 'ContainerSetting' });
|
||||
};
|
||||
|
||||
const search = async () => {
|
||||
let params = {
|
||||
page: paginationConfig.currentPage,
|
||||
|
@ -117,6 +137,6 @@ const buttons = [
|
|||
];
|
||||
|
||||
onMounted(() => {
|
||||
search();
|
||||
loadStatus();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
<template>
|
||||
<div>
|
||||
<Submenu activeName="template" />
|
||||
<el-card style="margin-top: 20px">
|
||||
<el-card width="30%" v-if="dockerStatus != 'Running'" class="mask-prompt">
|
||||
<span style="font-size: 14px">{{ $t('container.serviceUnavailable') }}</span>
|
||||
<el-button type="primary" link style="font-size: 14px; margin-bottom: 5px" @click="goSetting">
|
||||
【 {{ $t('container.setting') }} 】
|
||||
</el-button>
|
||||
<span style="font-size: 14px">{{ $t('container.startIn') }}</span>
|
||||
</el-card>
|
||||
<el-card style="margin-top: 20px" :class="{ mask: dockerStatus != 'Running' }">
|
||||
<ComplexTable :pagination-config="paginationConfig" v-model:selects="selects" :data="data" @search="search">
|
||||
<template #toolbar>
|
||||
<el-button icon="Plus" type="primary" @click="onOpenDialog('create')">
|
||||
|
@ -74,9 +81,10 @@ import { reactive, onMounted, ref } from 'vue';
|
|||
import { dateFromat } from '@/utils/util';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import OperatorDialog from '@/views/container/template/operator/index.vue';
|
||||
import { deleteComposeTemplate, searchComposeTemplate } from '@/api/modules/container';
|
||||
import { deleteComposeTemplate, loadDockerStatus, searchComposeTemplate } from '@/api/modules/container';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
import i18n from '@/lang';
|
||||
import router from '@/routers';
|
||||
|
||||
const data = ref();
|
||||
const selects = ref<any>([]);
|
||||
|
@ -90,6 +98,18 @@ const paginationConfig = reactive({
|
|||
total: 0,
|
||||
});
|
||||
|
||||
const dockerStatus = ref();
|
||||
const loadStatus = async () => {
|
||||
const res = await loadDockerStatus();
|
||||
dockerStatus.value = res.data;
|
||||
if (dockerStatus.value === 'Running') {
|
||||
search();
|
||||
}
|
||||
};
|
||||
const goSetting = async () => {
|
||||
router.push({ name: 'ContainerSetting' });
|
||||
};
|
||||
|
||||
const search = async () => {
|
||||
let params = {
|
||||
page: paginationConfig.currentPage,
|
||||
|
@ -157,6 +177,6 @@ const buttons = [
|
|||
];
|
||||
|
||||
onMounted(() => {
|
||||
search();
|
||||
loadStatus();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
<template>
|
||||
<div>
|
||||
<Submenu activeName="volume" />
|
||||
<el-card style="margin-top: 20px">
|
||||
<el-card width="30%" v-if="dockerStatus != 'Running'" class="mask-prompt">
|
||||
<span style="font-size: 14px">{{ $t('container.serviceUnavailable') }}</span>
|
||||
<el-button type="primary" link style="font-size: 14px; margin-bottom: 5px" @click="goSetting">
|
||||
【 {{ $t('container.setting') }} 】
|
||||
</el-button>
|
||||
<span style="font-size: 14px">{{ $t('container.startIn') }}</span>
|
||||
</el-card>
|
||||
<el-card style="margin-top: 20px" :class="{ mask: dockerStatus != 'Running' }">
|
||||
<ComplexTable :pagination-config="paginationConfig" v-model:selects="selects" :data="data" @search="search">
|
||||
<template #toolbar>
|
||||
<el-button icon="Plus" type="primary" @click="onCreate()">
|
||||
|
@ -46,10 +53,11 @@ import Submenu from '@/views/container/index.vue';
|
|||
import CodemirrorDialog from '@/components/codemirror-dialog/codemirror.vue';
|
||||
import { reactive, onMounted, ref } from 'vue';
|
||||
import { dateFromat } from '@/utils/util';
|
||||
import { deleteVolume, searchVolume, inspect } from '@/api/modules/container';
|
||||
import { deleteVolume, searchVolume, inspect, loadDockerStatus } from '@/api/modules/container';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import i18n from '@/lang';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
import router from '@/routers';
|
||||
|
||||
const detailInfo = ref();
|
||||
const codemirror = ref();
|
||||
|
@ -62,6 +70,18 @@ const paginationConfig = reactive({
|
|||
total: 0,
|
||||
});
|
||||
|
||||
const dockerStatus = ref();
|
||||
const loadStatus = async () => {
|
||||
const res = await loadDockerStatus();
|
||||
dockerStatus.value = res.data;
|
||||
if (dockerStatus.value === 'Running') {
|
||||
search();
|
||||
}
|
||||
};
|
||||
const goSetting = async () => {
|
||||
router.push({ name: 'ContainerSetting' });
|
||||
};
|
||||
|
||||
const dialogCreateRef = ref<DialogExpose>();
|
||||
|
||||
interface DialogExpose {
|
||||
|
@ -115,6 +135,6 @@ const buttons = [
|
|||
];
|
||||
|
||||
onMounted(() => {
|
||||
search();
|
||||
loadStatus();
|
||||
});
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue