fix: 解决容器端口冲突导致创建失败的问题 (#1770)

This commit is contained in:
ssongliu 2023-07-27 13:58:13 +08:00 committed by GitHub
parent 2a20ff0b79
commit 87a7cf3aca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 12 deletions

View File

@ -432,13 +432,15 @@ func (u *ContainerService) ContainerUpdate(req dto.ContainerOperate) error {
hostConf := oldContainer.HostConfig
var networkConf network.NetworkingConfig
if err := loadConfigInfo(req, config, hostConf, &networkConf); err != nil {
reCreateAfterUpdate(req.Name, client, oldContainer.Config, oldContainer.HostConfig, oldContainer.NetworkSettings)
return err
}
global.LOG.Infof("new container info %s has been update, now start to recreate", req.Name)
container, err := client.ContainerCreate(ctx, config, hostConf, &networkConf, &v1.Platform{}, req.Name)
if err != nil {
return fmt.Errorf("recreate contianer failed, err: %v", err)
reCreateAfterUpdate(req.Name, client, oldContainer.Config, oldContainer.HostConfig, oldContainer.NetworkSettings)
return fmt.Errorf("update contianer failed, err: %v", err)
}
global.LOG.Infof("update container %s successful! now check if the container is started.", req.Name)
if err := client.ContainerStart(ctx, container.ID, types.ContainerStartOptions{}); err != nil {
@ -481,13 +483,14 @@ func (u *ContainerService) ContainerUpgrade(req dto.ContainerUpgrade) error {
}
global.LOG.Infof("new container info %s has been update, now start to recreate", req.Name)
container, err := client.ContainerCreate(ctx, config, hostConf, &network.NetworkingConfig{}, &v1.Platform{}, req.Name)
container, err := client.ContainerCreate(ctx, config, hostConf, &networkConf, &v1.Platform{}, req.Name)
if err != nil {
return fmt.Errorf("recreate contianer failed, err: %v", err)
reCreateAfterUpdate(req.Name, client, oldContainer.Config, oldContainer.HostConfig, oldContainer.NetworkSettings)
return fmt.Errorf("upgrade contianer failed, err: %v", err)
}
global.LOG.Infof("update container %s successful! now check if the container is started.", req.Name)
global.LOG.Infof("upgrade container %s successful! now check if the container is started.", req.Name)
if err := client.ContainerStart(ctx, container.ID, types.ContainerStartOptions{}); err != nil {
return fmt.Errorf("update successful but start failed, err: %v", err)
return fmt.Errorf("upgrade successful but start failed, err: %v", err)
}
return nil
@ -795,7 +798,11 @@ func loadConfigInfo(req dto.ContainerOperate, config *container.Config, hostConf
config.Labels = stringsToMap(req.Labels)
config.ExposedPorts = exposeds
networkConf.EndpointsConfig = map[string]*network.EndpointSettings{req.Network: {}}
if len(req.Network) != 0 {
networkConf.EndpointsConfig = map[string]*network.EndpointSettings{req.Network: {}}
} else {
networkConf = &network.NetworkingConfig{}
}
hostConf.AutoRemove = req.AutoRemove
hostConf.CPUShares = req.CPUShares
@ -815,3 +822,24 @@ func loadConfigInfo(req dto.ContainerOperate, config *container.Config, hostConf
}
return nil
}
func reCreateAfterUpdate(name string, client *client.Client, config *container.Config, hostConf *container.HostConfig, networkConf *types.NetworkSettings) {
ctx := context.Background()
var oldNetworkConf network.NetworkingConfig
if networkConf != nil {
for networkKey := range networkConf.Networks {
oldNetworkConf.EndpointsConfig = map[string]*network.EndpointSettings{networkKey: {}}
break
}
}
oldContainer, err := client.ContainerCreate(ctx, config, hostConf, &oldNetworkConf, &v1.Platform{}, name)
if err != nil {
global.LOG.Errorf("recreate after container update failed, err: %v", err)
return
}
if err := client.ContainerStart(ctx, oldContainer.ID, types.ContainerStartOptions{}); err != nil {
global.LOG.Errorf("restart after container update failed, err: %v", err)
}
}

View File

@ -297,6 +297,7 @@ const onOpenDialog = async (
rowData: Partial<Container.ContainerHelper> = {
cmd: [],
cmdStr: '',
publishAllPorts: false,
exposedPorts: [],
cpuShares: 1024,
nanoCPUs: 0,

View File

@ -17,7 +17,13 @@
<el-input clearable v-model.trim="dialogData.rowData!.name" />
</el-form-item>
<el-form-item :label="$t('container.image')" prop="image">
<el-select class="widthClass" allow-create filterable v-model="dialogData.rowData!.image">
<el-select
class="widthClass"
:placeholder="$t('commons.msg.inputOrSelect')"
allow-create
filterable
v-model="dialogData.rowData!.image"
>
<el-option
v-for="(item, index) of images"
:key="index"
@ -159,7 +165,7 @@
v-for="(item, indexV) of volumes"
:key="indexV"
:value="item.option"
:label="item.option"
:label="item.option.substring(0, 12)"
/>
</el-select>
</td>
@ -301,13 +307,13 @@ const limits = ref<Container.ResourceLimit>({
});
const handleClose = () => {
emit('search');
drawerVisiable.value = false;
};
const rules = reactive({
name: [Rules.requiredInput, Rules.volumeName],
image: [Rules.requiredSelect],
network: [Rules.requiredSelect],
cpuShares: [Rules.integerNumberWith0, checkNumberRange(0, 262144)],
nanoCPUs: [Rules.floatNumber],
memory: [Rules.floatNumber],

View File

@ -41,9 +41,9 @@
</template>
<template #main>
<ComplexTable :pagination-config="paginationConfig" :data="data" @search="search">
<el-table-column label="ID" prop="id" min-width="60">
<el-table-column label="ID" prop="id" min-width="50">
<template #default="{ row }">
<Tooltip :islink="false" :text="row.id" />
<span>{{ row.id.replaceAll('sha256:', '').substring(0, 12) }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('container.tag')" prop="tags" min-width="160" fix>
@ -82,7 +82,6 @@
</template>
<script lang="ts" setup>
import Tooltip from '@/components/tooltip/index.vue';
import TableSetting from '@/components/table-setting/index.vue';
import { reactive, onMounted, ref } from 'vue';
import { dateFormat } from '@/utils/util';