diff --git a/backend/app/service/container.go b/backend/app/service/container.go index 54388f099..7ae2709a7 100644 --- a/backend/app/service/container.go +++ b/backend/app/service/container.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "io" "io/ioutil" "os/exec" "sort" @@ -22,6 +23,7 @@ import ( "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/network" + "github.com/docker/docker/client" "github.com/docker/go-connections/nat" v1 "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -193,14 +195,19 @@ func (u *ContainerService) ContainerCreate(req dto.ContainerCreate) error { } global.LOG.Infof("new container info %s has been made, now start to create", req.Name) - container, err := client.ContainerCreate(context.TODO(), config, hostConf, &network.NetworkingConfig{}, &v1.Platform{}, req.Name) + + ctx := context.Background() + if err := pullImages(ctx, client, req.Image); err != nil { + return err + } + container, err := client.ContainerCreate(ctx, config, hostConf, &network.NetworkingConfig{}, &v1.Platform{}, req.Name) if err != nil { - _ = client.ContainerRemove(context.Background(), req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true}) + _ = client.ContainerRemove(ctx, req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true}) return err } global.LOG.Infof("create container %s successful! now check if the container is started and delete the container information if it is not.", req.Name) - if err := client.ContainerStart(context.TODO(), container.ID, types.ContainerStartOptions{}); err != nil { - _ = client.ContainerRemove(context.Background(), req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true}) + if err := client.ContainerStart(ctx, container.ID, types.ContainerStartOptions{}); err != nil { + _ = client.ContainerRemove(ctx, req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true}) return fmt.Errorf("create successful but start failed, err: %v", err) } return nil @@ -323,3 +330,16 @@ func calculateNetwork(network map[string]types.NetworkStats) (float64, float64) } return rx, tx } + +func pullImages(ctx context.Context, client *client.Client, image string) error { + out, err := client.ImagePull(ctx, image, types.ImagePullOptions{}) + if err != nil { + return err + } + defer out.Close() + _, err = io.Copy(ioutil.Discard, out) + if err != nil { + return err + } + return nil +} diff --git a/frontend/src/api/modules/container.ts b/frontend/src/api/modules/container.ts index 3ceac9b87..6dd99a9fb 100644 --- a/frontend/src/api/modules/container.ts +++ b/frontend/src/api/modules/container.ts @@ -6,7 +6,7 @@ export const searchContainer = (params: Container.ContainerSearch) => { return http.post>(`/containers/search`, params); }; export const createContainer = (params: Container.ContainerCreate) => { - return http.post(`/containers`, params, 1200000); + return http.post(`/containers`, params, 3000000); }; export const logContainer = (params: Container.ContainerLogSearch) => { return http.post(`/containers/search/log`, params, 400000); diff --git a/frontend/src/views/container/image/index.vue b/frontend/src/views/container/image/index.vue index 3223b64b5..2aa40c54e 100644 --- a/frontend/src/views/container/image/index.vue +++ b/frontend/src/views/container/image/index.vue @@ -202,7 +202,7 @@ const buttons = [ { label: i18n.global.t('commons.button.delete'), click: async (row: Container.ImageInfo) => { - if (row.tags.length <= 1) { + if (!row.tags?.length || row.tags.length <= 1) { await useDeleteData(imageRemove, { names: [row.id] }, 'commons.msg.delete'); search(); return;