From ecc70c3ff11e332a4e8fbb138ce5071e2cbc27a3 Mon Sep 17 00:00:00 2001 From: ssongliu Date: Tue, 23 Sep 2025 18:38:42 +0800 Subject: [PATCH] feat: Container mounted volumes support shared customization --- agent/app/dto/container.go | 1 + agent/app/service/container.go | 4 + frontend/src/lang/modules/en.ts | 13 ++ frontend/src/lang/modules/es-es.ts | 14 ++ frontend/src/lang/modules/ja.ts | 13 ++ frontend/src/lang/modules/ko.ts | 13 ++ frontend/src/lang/modules/ms.ts | 13 ++ frontend/src/lang/modules/pt-br.ts | 14 ++ frontend/src/lang/modules/ru.ts | 14 ++ frontend/src/lang/modules/tr.ts | 13 ++ frontend/src/lang/modules/zh-Hant.ts | 13 ++ frontend/src/lang/modules/zh.ts | 13 ++ .../container/container/operate/index.vue | 93 +---------- .../container/container/operate/volume.vue | 156 ++++++++++++++++++ 14 files changed, 298 insertions(+), 89 deletions(-) create mode 100644 frontend/src/views/container/container/operate/volume.vue diff --git a/agent/app/dto/container.go b/agent/app/dto/container.go index b69295ca6066..d6e00a2a29d6 100644 --- a/agent/app/dto/container.go +++ b/agent/app/dto/container.go @@ -144,6 +144,7 @@ type VolumeHelper struct { SourceDir string `json:"sourceDir"` ContainerDir string `json:"containerDir"` Mode string `json:"mode"` + Shared string `json:"shared"` } type PortHelper struct { HostIP string `json:"hostIP"` diff --git a/agent/app/service/container.go b/agent/app/service/container.go index 5b6255bef146..6a98507fc148 100644 --- a/agent/app/service/container.go +++ b/agent/app/service/container.go @@ -1509,6 +1509,9 @@ func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *conta Source: volume.SourceDir, Target: volume.ContainerDir, ReadOnly: volume.Mode == "ro", + BindOptions: &mount.BindOptions{ + Propagation: mount.Propagation(volume.Shared), + }, }) config.Volumes[volume.ContainerDir] = struct{}{} } else { @@ -1555,6 +1558,7 @@ func loadVolumeBinds(binds []container.MountPoint) []dto.VolumeHelper { if bind.RW { volumeItem.Mode = "rw" } + volumeItem.Shared = string(bind.Propagation) datas = append(datas, volumeItem) } return datas diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index f4554b997012..741e13a920dd 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -848,6 +848,19 @@ const message = { volumeHelper: 'Ensure that the content of the storage volume is correct', modeRW: 'RW', modeR: 'R', + sharedLabel: 'Propagation Mode', + private: 'Private', + privateHelper: 'Mount changes in the container and host do not affect each other', + rprivate: 'Recursive Private', + rprivateHelper: 'All mounts in the container are completely isolated from the host', + shared: 'Shared', + sharedHelper: 'Mount changes in the host and container are visible to each other', + rshared: 'Recursive Shared', + rsharedHelper: 'All mount changes in the host and container are visible to each other', + slave: 'Slave', + slaveHelper: 'The container can see host mount changes, but its own changes do not affect the host', + rslave: 'Recursive Slave', + rslaveHelper: 'All mounts in the container can see host changes, but do not affect the host', mode: 'Mode', env: 'Environments', restartPolicy: 'Restart policy', diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index 825a99575d3f..ceb536db2b36 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -851,6 +851,20 @@ const message = { volumeHelper: 'Asegúrese de que el contenido del volumen de almacenamiento sea correcto', modeRW: 'RW', modeR: 'R', + sharedLabel: 'Modo de Propagación', + private: 'Privado', + privateHelper: 'Los cambios de montaje en el contenedor y el host no se afectan mutuamente', + rprivate: 'Privado Recursivo', + rprivateHelper: 'Todos los montajes en el contenedor están completamente aislados del host', + shared: 'Compartido', + sharedHelper: 'Los cambios de montaje en el host y el contenedor son visibles entre sí', + rshared: 'Compartido Recursivo', + rsharedHelper: 'Todos los cambios de montaje en el host y el contenedor son visibles entre sí', + slave: 'Esclavo', + slaveHelper: + 'El contenedor puede ver los cambios de montaje del host, pero sus propios cambios no afectan al host', + rslave: 'Esclavo Recursivo', + rslaveHelper: 'Todos los montajes en el contenedor pueden ver los cambios del host, pero no afectan al host', mode: 'Modo', env: 'Entornos', restartPolicy: 'Política de reinicio', diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 114e1d99037c..2e3d0b7621a9 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -825,6 +825,19 @@ const message = { volumeHelper: 'ストレージボリュームのコンテンツが正しいことを確認してください', modeRW: 'rw', modeR: 'r', + sharedLabel: '伝播モード', + private: 'プライベート', + privateHelper: 'コンテナ内とホストのマウント変更は互いに干渉しません', + rprivate: '再帰的プライベート', + rprivateHelper: 'コンテナ内のすべてのマウントはホストから完全に隔離されています', + shared: '共有', + sharedHelper: 'ホストとコンテナ内のマウント変更は互いに表示されます', + rshared: '再帰的共有', + rsharedHelper: 'ホストとコンテナ内のすべてのマウント変更が互いに表示されます', + slave: 'スレーブ', + slaveHelper: 'コンテナはホストのマウント変更を確認できますが、自身の変更はホストに影響しません', + rslave: '再帰的スレーブ', + rslaveHelper: 'コンテナ内のすべてのマウントはホストの変更を確認できますが、ホストに影響しません', mode: 'モード', env: '環境', restartPolicy: 'ポリシーを再起動します', diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index 4d1658b5823c..d9a04c3eb33a 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -819,6 +819,19 @@ const message = { volumeHelper: '저장소 볼륨의 내용이 올바른지 확인하십시오.', modeRW: '읽기/쓰기', modeR: '읽기 전용', + sharedLabel: '전파 모드', + private: '비공개', + privateHelper: '컨테이너와 호스트의 마운트 변경 사항이 서로 영향을 주지 않음', + rprivate: '재귀적 비공개', + rprivateHelper: '컨테이너 내 모든 마운트가 호스트와 완전히 격리됨', + shared: '공유', + sharedHelper: '호스트와 컨테이너의 마운트 변경 사항이 서로 보임', + rshared: '재귀적 공유', + rsharedHelper: '호스트와 컨테이너의 모든 마운트 변경 사항이 서로 보임', + slave: '슬레이브', + slaveHelper: '컨테이너는 호스트 마운트 변경 사항을 볼 수 있지만, 자신의 변경 사항은 호스트에 영향을 주지 않음', + rslave: '재귀적 슬레이브', + rslaveHelper: '컨테이너 내 모든 마운트가 호스트 변경 사항을 볼 수 있지만 호스트에 영향을 주지 않음', mode: '모드', env: '환경', restartPolicy: '재시작 정책', diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index a8589d287f4f..20ff93898fde 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -841,6 +841,19 @@ const message = { volumeHelper: 'Pastikan kandungan volum storan adalah betul', modeRW: 'RW', modeR: 'R', + sharedLabel: 'Mod Penyebaran', + private: 'Peribadi', + privateHelper: 'Perubahan pemasangan dalam bekas dan hos tidak saling mempengaruhi', + rprivate: 'Peribadi Rekursif', + rprivateHelper: 'Semua pemasangan dalam bekas diasingkan sepenuhnya dari hos', + shared: 'Berkongsi', + sharedHelper: 'Perubahan pemasangan dalam hos dan bekas kelihatan antara satu sama lain', + rshared: 'Berkongsi Rekursif', + rsharedHelper: 'Semua perubahan pemasangan dalam hos dan bekas kelihatan antara satu sama lain', + slave: 'Hamba', + slaveHelper: 'Bekas dapat melihat perubahan pemasangan hos, tetapi perubahan sendiri tidak mempengaruhi hos', + rslave: 'Hamba Rekursif', + rslaveHelper: 'Semua pemasangan dalam bekas dapat melihat perubahan hos, tetapi tidak mempengaruhi hos', mode: 'Mod', env: 'Persekitaran', restartPolicy: 'Polisi Mulakan Semula', diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index dd9f0946614b..12b8c091ea4f 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -837,6 +837,20 @@ const message = { volumeHelper: 'Certifique-se de que o conteúdo do volume de armazenamento está correto', modeRW: 'RW', modeR: 'R', + sharedLabel: 'Modo de Propagação', + private: 'Privado', + privateHelper: 'As alterações de montagem no container e no host não se afetam mutuamente', + rprivate: 'Privado Recursivo', + rprivateHelper: 'Todas as montagens no container estão completamente isoladas do host', + shared: 'Compartilhado', + sharedHelper: 'As alterações de montagem no host e no container são visíveis entre si', + rshared: 'Compartilhado Recursivo', + rsharedHelper: 'Todas as alterações de montagem no host e no container são visíveis entre sí', + slave: 'Escravo', + slaveHelper: + 'O container pode ver as alterações de montagem do host, mas suas próprias alterações não afetam o host', + rslave: 'Escravo Recursivo', + rslaveHelper: 'Todas as montagens no container podem ver as alterações do host, mas não afetam o host', mode: 'Modo', env: 'Ambientes', restartPolicy: 'Política de reinício', diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index fd5a2f1dcf02..393296c56cee 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -837,6 +837,20 @@ const message = { volumeHelper: 'Убедитесь, что содержимое тома хранения корректно', modeRW: 'Чтение-Запись', modeR: 'Только чтение', + sharedLabel: 'Режим Распространения', + private: 'Приватный', + privateHelper: 'Изменения монтирования в контейнере и хосте не влияют друг на друга', + rprivate: 'Рекурсивный Приватный', + rprivateHelper: 'Все монтирования в контейнере полностью изолированы от хоста', + shared: 'Общий', + sharedHelper: 'Изменения монтирования в хосте и контейнере видны друг другу', + rshared: 'Рекурсивный Общий', + rsharedHelper: 'Все изменения монтирования в хосте и контейнере видны друг другу', + slave: 'Подчиненный', + slaveHelper: + 'Контейнер может видеть изменения монтирования хоста, но его собственные изменения не влияют на хост', + rslave: 'Рекурсивный Подчиненный', + rslaveHelper: 'Все монтирования в контейнере могут видеть изменения хоста, но не влияют на хост', mode: 'Режим', env: 'Переменные окружения', restartPolicy: 'Политика перезапуска', diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index 8a912e54985d..06857bfe100f 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -857,6 +857,19 @@ const message = { volumeHelper: 'Depolama biriminin içeriğinin doğru olduğundan emin olun', modeRW: 'RW', modeR: 'R', + sharedLabel: 'Yayılma Modu', + private: 'Özel', + privateHelper: 'Konteyner ve hosttaki bağlama değişiklikleri birbirini etkilemez', + rprivate: 'Özyinelemeli Özel', + rprivateHelper: 'Konteynerdeki tüm bağlamalar hosttan tamamen izole edilmiştir', + shared: 'Paylaşılan', + sharedHelper: 'Host ve konteynerdeki bağlama değişiklikleri birbirine görünür', + rshared: 'Özyinelemeli Paylaşılan', + rsharedHelper: 'Host ve konteynerdeki tüm bağlama değişiklikleri birbirine görünür', + slave: 'Bağımlı', + slaveHelper: 'Konteyner host bağlama değişikliklerini görebilir, ancak kendi değişiklikleri hostu etkilemez', + rslave: 'Özyinelemeli Bağımlı', + rslaveHelper: 'Konteynerdeki tüm bağlamalar host değişikliklerini görebilir, ancak hostu etkilemez', mode: 'Mod', env: 'Ortamlar', restartPolicy: 'Yeniden başlatma politikası', diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index fbe8609200b2..ab001ee7d541 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -813,6 +813,19 @@ const message = { volumeHelper: '請確認磁碟區內容輸入正確', modeRW: '讀寫', modeR: '唯讀', + sharedLabel: '傳播模式', + private: '私有', + privateHelper: '容器裡的掛載變化和主機互不干擾', + rprivate: '遞歸私有', + rprivateHelper: '容器裡所有掛載都和主機完全隔離', + shared: '共享', + sharedHelper: '主機和容器裡的掛載變化互相可見', + rshared: '遞歸共享', + rsharedHelper: '主機和容器裡所有掛載變化都互相可見', + slave: '從屬', + slaveHelper: '容器能看見主機的掛載變化,但自己的變化不影響主機', + rslave: '遞歸從屬', + rslaveHelper: '容器裡所有掛載都能看見主機變化,但不影響主機', mode: '權限', env: '環境變數', restartPolicy: '重啟規則', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 76dea31fd593..0f8fdf699498 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -812,6 +812,19 @@ const message = { volumeHelper: '请确认存储卷内容输入正确', modeRW: '读写', modeR: '只读', + sharedLabel: '传播模式', + private: '私有', + privateHelper: '容器里的挂载变化和主机互不干扰', + rprivate: '递归私有', + rprivateHelper: '容器里所有挂载都和主机完全隔离', + shared: '共享', + sharedHelper: '主机和容器里的挂载变化互相可见', + rshared: '递归共享', + rsharedHelper: '主机和容器里所有挂载变化都互相可见', + slave: '从属', + slaveHelper: '容器能看见主机的挂载变化,但自己的变化不影响主机', + rslave: '递归从属', + rslaveHelper: '容器里所有挂载都能看见主机变化,但不影响主机', mode: '权限', env: '环境变量', restartPolicy: '重启规则', diff --git a/frontend/src/views/container/container/operate/index.vue b/frontend/src/views/container/container/operate/index.vue index 3c01440faad2..57c6ee16a834 100644 --- a/frontend/src/views/container/container/operate/index.vue +++ b/frontend/src/views/container/container/operate/index.vue @@ -193,75 +193,7 @@ - - - - - - - - - - - - - - - - - - - - {{ $t('commons.button.add') }} - - + @@ -439,9 +371,9 @@ import { Rules, checkFloatNumberRange, checkNumberRange } from '@/global/form-ru import i18n from '@/lang'; import { ElForm } from 'element-plus'; import Confirm from '@/views/container/container/operate/confirm.vue'; +import Volume from '@/views/container/container/operate/volume.vue'; import { listImage, - listVolume, createContainer, updateContainer, loadResourceLimit, @@ -460,6 +392,7 @@ import { routerToName } from '@/utils/router'; const loading = ref(false); const isCreate = ref(); const confirmRef = ref(); +const volumeRef = ref(); const form = reactive({ taskID: '', containerID: '', @@ -560,13 +493,11 @@ const search = async () => { } loadLimit(); loadImageOptions(); - loadVolumeOptions(); loadNetworkOptions(); }; const taskLogRef = ref(); const images = ref(); -const volumes = ref(); const networks = ref(); const limits = ref({ cpu: null as number, @@ -613,19 +544,6 @@ const goRouter = async () => { routerToName('AppInstalled'); }; -const handleVolumesAdd = () => { - let item = { - type: 'bind', - sourceDir: '', - containerDir: '', - mode: 'rw', - }; - form.volumes.push(item); -}; -const handleVolumesDelete = (index: number) => { - form.volumes.splice(index, 1); -}; - const loadLimit = async () => { const res = await loadResourceLimit(); limits.value = res.data; @@ -636,15 +554,12 @@ const loadImageOptions = async () => { const res = await listImage(); images.value = res.data; }; -const loadVolumeOptions = async () => { - const res = await listVolume(); - volumes.value = res.data; -}; const loadNetworkOptions = async () => { const res = await listNetwork(); networks.value = res.data; }; const onSubmit = async (formEl: FormInstance | undefined) => { + form.volumes = volumeRef.value.loadVolumes(); if (form.volumes.length !== 0) { for (const item of form.volumes) { if (!item.containerDir || !item.sourceDir) { diff --git a/frontend/src/views/container/container/operate/volume.vue b/frontend/src/views/container/container/operate/volume.vue new file mode 100644 index 000000000000..9c506c2b2e37 --- /dev/null +++ b/frontend/src/views/container/container/operate/volume.vue @@ -0,0 +1,156 @@ + + + + +