mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 14:08:06 +08:00
feat: 面板代理服务器提供 docker 代理 (#6986)
This commit is contained in:
parent
cccbaafd1b
commit
204f9f1fbc
@ -198,6 +198,23 @@ func (u *DockerService) UpdateConf(req dto.SettingUpdate) error {
|
|||||||
daemonMap["exec-opts"] = []string{"native.cgroupdriver=systemd"}
|
daemonMap["exec-opts"] = []string{"native.cgroupdriver=systemd"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "http-proxy", "https-proxy":
|
||||||
|
delete(daemonMap, "proxies")
|
||||||
|
if len(req.Value) > 0 {
|
||||||
|
proxies := map[string]interface{}{
|
||||||
|
req.Key: req.Value,
|
||||||
|
}
|
||||||
|
daemonMap["proxies"] = proxies
|
||||||
|
}
|
||||||
|
case "socks5-proxy":
|
||||||
|
delete(daemonMap, "proxies")
|
||||||
|
if len(req.Value) > 0 {
|
||||||
|
proxies := map[string]interface{}{
|
||||||
|
"http-proxy": req.Value,
|
||||||
|
"https-proxy": req.Value,
|
||||||
|
}
|
||||||
|
daemonMap["proxies"] = proxies
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if len(daemonMap) == 0 {
|
if len(daemonMap) == 0 {
|
||||||
_ = os.Remove(constant.DaemonJsonPath)
|
_ = os.Remove(constant.DaemonJsonPath)
|
||||||
|
@ -1392,11 +1392,14 @@ const message = {
|
|||||||
proxyHelper: 'After setting up the proxy server, it will be effective in the following scenarios:',
|
proxyHelper: 'After setting up the proxy server, it will be effective in the following scenarios:',
|
||||||
proxyHelper1: 'Downloading and synchronizing installation packages from the app store (Professional)',
|
proxyHelper1: 'Downloading and synchronizing installation packages from the app store (Professional)',
|
||||||
proxyHelper2: 'System version upgrades and retrieving update information (Professional)',
|
proxyHelper2: 'System version upgrades and retrieving update information (Professional)',
|
||||||
|
proxyHelper4: 'Docker Daemon provides network access proxy (Professional)',
|
||||||
proxyHelper3: 'Verification and synchronization of system licenses',
|
proxyHelper3: 'Verification and synchronization of system licenses',
|
||||||
proxyType: 'Proxy Type',
|
proxyType: 'Proxy Type',
|
||||||
proxyUrl: 'Proxy Address',
|
proxyUrl: 'Proxy Address',
|
||||||
proxyPort: 'Proxy Port',
|
proxyPort: 'Proxy Port',
|
||||||
proxyPasswdKeep: 'Remember Password',
|
proxyPasswdKeep: 'Remember Password',
|
||||||
|
proxyDocker: 'Docker Proxy',
|
||||||
|
proxyDockerHelper: 'Docker Daemon provides network access proxy',
|
||||||
systemIPWarning: 'The server address is not currently set. Please set it in the control panel first!',
|
systemIPWarning: 'The server address is not currently set. Please set it in the control panel first!',
|
||||||
systemIPWarning1: 'The current server address is set to {0}, and quick redirection is not possible!',
|
systemIPWarning1: 'The current server address is set to {0}, and quick redirection is not possible!',
|
||||||
defaultNetwork: 'Network Card',
|
defaultNetwork: 'Network Card',
|
||||||
|
@ -1314,11 +1314,14 @@ const message = {
|
|||||||
proxyHelper: '設置代理伺服器後,將在以下場景中生效:',
|
proxyHelper: '設置代理伺服器後,將在以下場景中生效:',
|
||||||
proxyHelper1: '應用商店的安裝包下載和同步(專業版功能)',
|
proxyHelper1: '應用商店的安裝包下載和同步(專業版功能)',
|
||||||
proxyHelper2: '系統版本升級及獲取更新說明(專業版功能)',
|
proxyHelper2: '系統版本升級及獲取更新說明(專業版功能)',
|
||||||
|
proxyHelper4: 'Docker Daemon 提供網絡訪問代理(專業版功能)',
|
||||||
proxyHelper3: '系統許可證的驗證和同步',
|
proxyHelper3: '系統許可證的驗證和同步',
|
||||||
proxyType: '代理類型',
|
proxyType: '代理類型',
|
||||||
proxyUrl: '代理地址',
|
proxyUrl: '代理地址',
|
||||||
proxyPort: '代理端口',
|
proxyPort: '代理端口',
|
||||||
proxyPasswdKeep: '記住密碼',
|
proxyPasswdKeep: '記住密碼',
|
||||||
|
proxyDocker: 'Docker 代理',
|
||||||
|
proxyDockerHelper: '為 Docker Daemon 提供網絡訪問代理',
|
||||||
systemIPWarning: '當前未設置服務器地址,請先在面板設置中設置!',
|
systemIPWarning: '當前未設置服務器地址,請先在面板設置中設置!',
|
||||||
systemIPWarning1: '當前服務器地址設置為 {0},無法快速跳轉!',
|
systemIPWarning1: '當前服務器地址設置為 {0},無法快速跳轉!',
|
||||||
defaultNetwork: '默認網卡',
|
defaultNetwork: '默認網卡',
|
||||||
|
@ -1317,10 +1317,13 @@ const message = {
|
|||||||
proxyHelper1: '应用商店的安装包下载和同步(专业版功能)',
|
proxyHelper1: '应用商店的安装包下载和同步(专业版功能)',
|
||||||
proxyHelper2: '系统版本升级及获取更新说明(专业版功能)',
|
proxyHelper2: '系统版本升级及获取更新说明(专业版功能)',
|
||||||
proxyHelper3: '系统许可证的验证和同步',
|
proxyHelper3: '系统许可证的验证和同步',
|
||||||
|
proxyHelper4: 'Docker Daemon 提供网络访问代理(专业版功能)',
|
||||||
proxyType: '代理类型',
|
proxyType: '代理类型',
|
||||||
proxyUrl: '代理地址',
|
proxyUrl: '代理地址',
|
||||||
proxyPort: '代理端口',
|
proxyPort: '代理端口',
|
||||||
proxyPasswdKeep: '记住密码',
|
proxyPasswdKeep: '记住密码',
|
||||||
|
proxyDocker: 'Docker 代理',
|
||||||
|
proxyDockerHelper: '为 Docker Daemon 提供网络访问代理',
|
||||||
systemIPWarning: '当前未设置服务器地址,请先在面板设置中设置!',
|
systemIPWarning: '当前未设置服务器地址,请先在面板设置中设置!',
|
||||||
systemIPWarning1: '当前服务器地址设置为 {0},无法快速跳转!',
|
systemIPWarning1: '当前服务器地址设置为 {0},无法快速跳转!',
|
||||||
defaultNetwork: '默认网卡',
|
defaultNetwork: '默认网卡',
|
||||||
|
@ -589,3 +589,29 @@ export const getFileType = (extension: string) => {
|
|||||||
});
|
});
|
||||||
return type;
|
return type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const escapeProxyURL = (url: string): string => {
|
||||||
|
const encodeMap: { [key: string]: string } = {
|
||||||
|
':': '%%3A',
|
||||||
|
'/': '%%2F',
|
||||||
|
'?': '%%3F',
|
||||||
|
'#': '%%23',
|
||||||
|
'[': '%%5B',
|
||||||
|
']': '%%5D',
|
||||||
|
'@': '%%40',
|
||||||
|
'!': '%%21',
|
||||||
|
$: '%%24',
|
||||||
|
'&': '%%26',
|
||||||
|
"'": '%%27',
|
||||||
|
'(': '%%28',
|
||||||
|
')': '%%29',
|
||||||
|
'*': '%%2A',
|
||||||
|
'+': '%%2B',
|
||||||
|
',': '%%2C',
|
||||||
|
';': '%%3B',
|
||||||
|
'=': '%%3D',
|
||||||
|
'%': '%%25',
|
||||||
|
};
|
||||||
|
|
||||||
|
return url.replace(/[\/:?#[\]@!$&'()*+,;=%~]/g, (match) => encodeMap[match] || match);
|
||||||
|
};
|
||||||
|
@ -239,6 +239,7 @@ const form = reactive({
|
|||||||
proxyUser: '',
|
proxyUser: '',
|
||||||
proxyPasswd: '',
|
proxyPasswd: '',
|
||||||
proxyPasswdKeep: '',
|
proxyPasswdKeep: '',
|
||||||
|
proxyDocker: '',
|
||||||
|
|
||||||
proHideMenus: ref(i18n.t('setting.unSetting')),
|
proHideMenus: ref(i18n.t('setting.unSetting')),
|
||||||
hideMenuList: '',
|
hideMenuList: '',
|
||||||
@ -302,6 +303,7 @@ const search = async () => {
|
|||||||
form.theme = xpackRes.data.theme || globalStore.themeConfig.theme;
|
form.theme = xpackRes.data.theme || globalStore.themeConfig.theme;
|
||||||
form.themeColor = JSON.parse(xpackRes.data.themeColor);
|
form.themeColor = JSON.parse(xpackRes.data.themeColor);
|
||||||
globalStore.themeConfig.themeColor = xpackRes.data.themeColor;
|
globalStore.themeConfig.themeColor = xpackRes.data.themeColor;
|
||||||
|
form.proxyDocker = xpackRes.data.proxyDocker;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
form.theme = res.data.theme;
|
form.theme = res.data.theme;
|
||||||
@ -355,6 +357,7 @@ const onChangeProxy = () => {
|
|||||||
user: form.proxyUser,
|
user: form.proxyUser,
|
||||||
passwd: form.proxyPasswd,
|
passwd: form.proxyPasswd,
|
||||||
passwdKeep: form.proxyPasswdKeep,
|
passwdKeep: form.proxyPasswdKeep,
|
||||||
|
proxyDocker: form.proxyDocker,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const onChangeNetwork = () => {
|
const onChangeNetwork = () => {
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
<ul style="margin-left: -20px">
|
<ul style="margin-left: -20px">
|
||||||
<li v-if="isProductPro">{{ $t('setting.proxyHelper1') }}</li>
|
<li v-if="isProductPro">{{ $t('setting.proxyHelper1') }}</li>
|
||||||
<li v-if="isProductPro">{{ $t('setting.proxyHelper2') }}</li>
|
<li v-if="isProductPro">{{ $t('setting.proxyHelper2') }}</li>
|
||||||
|
<li v-if="isProductPro">{{ $t('setting.proxyHelper4') }}</li>
|
||||||
<li>{{ $t('setting.proxyHelper3') }}</li>
|
<li>{{ $t('setting.proxyHelper3') }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
@ -59,6 +60,10 @@
|
|||||||
:label="$t('setting.proxyPasswdKeep')"
|
:label="$t('setting.proxyPasswdKeep')"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item v-if="isProductPro">
|
||||||
|
<el-checkbox v-model="form.proxyDocker" :label="$t('setting.proxyDocker')" />
|
||||||
|
<span class="input-help">{{ $t('setting.proxyDockerHelper') }}</span>
|
||||||
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -74,6 +79,8 @@
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
|
|
||||||
|
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmit" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -87,11 +94,16 @@ import DrawerHeader from '@/components/drawer-header/index.vue';
|
|||||||
import { updateProxy } from '@/api/modules/setting';
|
import { updateProxy } from '@/api/modules/setting';
|
||||||
import { GlobalStore } from '@/store';
|
import { GlobalStore } from '@/store';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { updateXpackSettingByKey } from '@/utils/xpack';
|
||||||
|
import { updateDaemonJson } from '@/api/modules/container';
|
||||||
|
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
|
||||||
|
import { escapeProxyURL } from '@/utils/util';
|
||||||
|
|
||||||
const globalStore = GlobalStore();
|
const globalStore = GlobalStore();
|
||||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||||
const { isProductPro } = storeToRefs(globalStore);
|
const { isProductPro } = storeToRefs(globalStore);
|
||||||
|
|
||||||
|
const confirmDialogRef = ref();
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
proxyType: [Rules.requiredSelect],
|
proxyType: [Rules.requiredSelect],
|
||||||
@ -101,6 +113,7 @@ const rules = reactive({
|
|||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const passwordVisible = ref<boolean>(false);
|
const passwordVisible = ref<boolean>(false);
|
||||||
|
const proxyDockerVisible = ref<boolean>(false);
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
proxyUrl: '',
|
proxyUrl: '',
|
||||||
proxyType: '',
|
proxyType: '',
|
||||||
@ -110,6 +123,7 @@ const form = reactive({
|
|||||||
proxyPasswd: '',
|
proxyPasswd: '',
|
||||||
proxyPasswdKeep: '',
|
proxyPasswdKeep: '',
|
||||||
proxyPasswdKeepItem: false,
|
proxyPasswdKeepItem: false,
|
||||||
|
proxyDocker: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
interface DialogProps {
|
interface DialogProps {
|
||||||
@ -119,6 +133,7 @@ interface DialogProps {
|
|||||||
user: string;
|
user: string;
|
||||||
passwd: string;
|
passwd: string;
|
||||||
passwdKeep: string;
|
passwdKeep: string;
|
||||||
|
proxyDocker: string;
|
||||||
}
|
}
|
||||||
const acceptParams = (params: DialogProps): void => {
|
const acceptParams = (params: DialogProps): void => {
|
||||||
if (params.url) {
|
if (params.url) {
|
||||||
@ -134,6 +149,8 @@ const acceptParams = (params: DialogProps): void => {
|
|||||||
form.proxyPortItem = params.port ? Number(params.port) : 7890;
|
form.proxyPortItem = params.port ? Number(params.port) : 7890;
|
||||||
form.proxyUser = params.user;
|
form.proxyUser = params.user;
|
||||||
form.proxyPasswd = params.passwd;
|
form.proxyPasswd = params.passwd;
|
||||||
|
form.proxyDocker = params.proxyDocker !== '';
|
||||||
|
proxyDockerVisible.value = params.proxyDocker !== '';
|
||||||
passwordVisible.value = true;
|
passwordVisible.value = true;
|
||||||
form.proxyPasswdKeepItem = params.passwdKeep === 'Enable';
|
form.proxyPasswdKeepItem = params.passwdKeep === 'Enable';
|
||||||
};
|
};
|
||||||
@ -150,6 +167,7 @@ const submitChangePassword = async (formEl: FormInstance | undefined) => {
|
|||||||
proxyUser: isClose ? '' : form.proxyUser,
|
proxyUser: isClose ? '' : form.proxyUser,
|
||||||
proxyPasswd: isClose ? '' : form.proxyPasswd,
|
proxyPasswd: isClose ? '' : form.proxyPasswd,
|
||||||
proxyPasswdKeep: '',
|
proxyPasswdKeep: '',
|
||||||
|
proxyDocker: isClose ? false : form.proxyDocker,
|
||||||
};
|
};
|
||||||
if (!isClose) {
|
if (!isClose) {
|
||||||
params.proxyPasswdKeep = form.proxyPasswdKeepItem ? 'Enable' : 'Disable';
|
params.proxyPasswdKeep = form.proxyPasswdKeepItem ? 'Enable' : 'Disable';
|
||||||
@ -157,19 +175,78 @@ const submitChangePassword = async (formEl: FormInstance | undefined) => {
|
|||||||
if (form.proxyType === 'http' || form.proxyType === 'https') {
|
if (form.proxyType === 'http' || form.proxyType === 'https') {
|
||||||
params.proxyUrl = form.proxyType + '://' + form.proxyUrl;
|
params.proxyUrl = form.proxyType + '://' + form.proxyUrl;
|
||||||
}
|
}
|
||||||
loading.value = true;
|
if (
|
||||||
await updateProxy(params)
|
isProductPro.value &&
|
||||||
.then(async () => {
|
(params.proxyDocker ||
|
||||||
loading.value = false;
|
(proxyDockerVisible.value && isClose) ||
|
||||||
emit('search');
|
(proxyDockerVisible.value && !isClose) ||
|
||||||
passwordVisible.value = false;
|
(proxyDockerVisible.value && !params.proxyDocker))
|
||||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
) {
|
||||||
})
|
let confirmParams = {
|
||||||
.catch(() => {
|
header: i18n.global.t('database.confChange'),
|
||||||
loading.value = false;
|
operationInfo: i18n.global.t('database.restartNowHelper'),
|
||||||
});
|
submitInputInfo: i18n.global.t('database.restartNow'),
|
||||||
|
};
|
||||||
|
confirmDialogRef.value!.acceptParams(confirmParams);
|
||||||
|
} else {
|
||||||
|
loading.value = true;
|
||||||
|
await updateProxy(params)
|
||||||
|
.then(async () => {
|
||||||
|
loading.value = false;
|
||||||
|
emit('search');
|
||||||
|
passwordVisible.value = false;
|
||||||
|
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onSubmit = async () => {
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
let isClose = form.proxyType === '' || form.proxyType === 'close';
|
||||||
|
let params = {
|
||||||
|
proxyType: isClose ? '' : form.proxyType,
|
||||||
|
proxyUrl: isClose ? '' : form.proxyUrl,
|
||||||
|
proxyPort: isClose ? '' : form.proxyPortItem + '',
|
||||||
|
proxyUser: isClose ? '' : form.proxyUser,
|
||||||
|
proxyPasswd: isClose ? '' : form.proxyPasswd,
|
||||||
|
proxyPasswdKeep: '',
|
||||||
|
proxyDocker: isClose ? false : form.proxyDocker,
|
||||||
|
};
|
||||||
|
if (!isClose) {
|
||||||
|
params.proxyPasswdKeep = form.proxyPasswdKeepItem ? 'Enable' : 'Disable';
|
||||||
|
}
|
||||||
|
let proxyPort = params.proxyPort ? `:${params.proxyPort}` : '';
|
||||||
|
let proxyUser = params.proxyUser ? `${escapeProxyURL(params.proxyUser)}` : '';
|
||||||
|
let proxyPasswd = '';
|
||||||
|
if (params.proxyUser) {
|
||||||
|
proxyPasswd = params.proxyPasswd ? `:${escapeProxyURL(params.proxyPasswd)}@` : '@';
|
||||||
|
}
|
||||||
|
|
||||||
|
let proxyUrl = form.proxyType + '://' + proxyUser + proxyPasswd + form.proxyUrl + proxyPort;
|
||||||
|
if (form.proxyType === 'http' || form.proxyType === 'https') {
|
||||||
|
params.proxyUrl = form.proxyType + '://' + form.proxyUrl;
|
||||||
|
}
|
||||||
|
await updateProxy(params);
|
||||||
|
if (isClose || params.proxyDocker === false) {
|
||||||
|
params.proxyUrl = '';
|
||||||
|
}
|
||||||
|
await updateXpackSettingByKey('ProxyDocker', proxyUrl);
|
||||||
|
await updateDaemonJson(`${form.proxyType}-proxy`, proxyUrl);
|
||||||
|
emit('search');
|
||||||
|
handleClose();
|
||||||
|
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
passwordVisible.value = false;
|
passwordVisible.value = false;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user