Show a host-specific Docker remote-API setup script in Settings
When adding/editing a Docker integration with a tcp:// or http:// remote URL, display a copyable systemd override + curl verification script scoped to the entered host:port, so enabling the daemon's API doesn't require looking up the steps separately.
This commit is contained in:
parent
4a4a5a01b3
commit
628187befb
1 changed files with 75 additions and 0 deletions
|
|
@ -784,6 +784,77 @@ function SshHostsSection() {
|
||||||
|
|
||||||
type NewIntegrationDraft = { id: number; type: string; values: Record<string, string> }
|
type NewIntegrationDraft = { id: number; type: string; values: Record<string, string> }
|
||||||
|
|
||||||
|
function dockerHostInfo(baseUrl: string): { host: string; port: string } | null {
|
||||||
|
if (!baseUrl || baseUrl.startsWith('unix://')) return null
|
||||||
|
try {
|
||||||
|
const u = new URL(baseUrl.replace(/^tcp:\/\//, 'http://'))
|
||||||
|
if (u.protocol !== 'http:' && u.protocol !== 'https:') return null
|
||||||
|
if (!u.hostname) return null
|
||||||
|
return { host: u.hostname, port: u.port || '2375' }
|
||||||
|
} catch {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function DockerSetupHint({ baseUrl }: { baseUrl: string }) {
|
||||||
|
const [copied, setCopied] = useState(false)
|
||||||
|
const info = dockerHostInfo(baseUrl)
|
||||||
|
if (!info) return null
|
||||||
|
|
||||||
|
const script = `sudo mkdir -p /etc/systemd/system/docker.service.d
|
||||||
|
sudo tee /etc/systemd/system/docker.service.d/override.conf > /dev/null <<EOF
|
||||||
|
[Service]
|
||||||
|
ExecStart=
|
||||||
|
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://${info.host}:${info.port}
|
||||||
|
EOF
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl restart docker
|
||||||
|
curl http://${info.host}:${info.port}/version`
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
marginTop: '12px',
|
||||||
|
padding: '12px 14px',
|
||||||
|
borderRadius: '8px',
|
||||||
|
border: '1px solid rgba(200,164,52,0.12)',
|
||||||
|
backgroundColor: 'rgba(255,255,255,0.02)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="flex items-center justify-between" style={{ marginBottom: '8px' }}>
|
||||||
|
<span style={{ fontSize: '11px', color: '#7A7D85' }}>
|
||||||
|
Run this on <strong style={{ color: '#E8E6E0' }}>{info.host}</strong> to expose its Docker API on port {info.port}:
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(script)
|
||||||
|
setCopied(true)
|
||||||
|
setTimeout(() => setCopied(false), 1500)
|
||||||
|
}}
|
||||||
|
className="flex items-center gap-1 cursor-pointer border-none bg-transparent"
|
||||||
|
style={{ fontSize: '10.5px', fontWeight: 600, color: copied ? '#2ECC71' : '#C8A434', flexShrink: 0 }}
|
||||||
|
>
|
||||||
|
{copied ? <Check size={11} /> : null}
|
||||||
|
{copied ? 'Copied' : 'Copy script'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<pre
|
||||||
|
style={{
|
||||||
|
fontSize: '10.5px',
|
||||||
|
color: '#9DA0A8',
|
||||||
|
fontFamily: 'monospace',
|
||||||
|
whiteSpace: 'pre-wrap',
|
||||||
|
wordBreak: 'break-all',
|
||||||
|
margin: 0,
|
||||||
|
lineHeight: 1.5,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{script}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function IntegrationsSection() {
|
function IntegrationsSection() {
|
||||||
const { user } = useAuth()
|
const { user } = useAuth()
|
||||||
const isAdmin = user?.role === 'admin'
|
const isAdmin = user?.role === 'admin'
|
||||||
|
|
@ -1051,6 +1122,9 @@ function IntegrationsSection() {
|
||||||
'••••••••••••',
|
'••••••••••••',
|
||||||
existing,
|
existing,
|
||||||
)}
|
)}
|
||||||
|
{def.type === 'docker' && (
|
||||||
|
<DockerSetupHint baseUrl={draft.baseUrl ?? existing.config.baseUrl ?? ''} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|
@ -1100,6 +1174,7 @@ function IntegrationsSection() {
|
||||||
(f, value) => setNewDraftField(draft.id, f.key, value),
|
(f, value) => setNewDraftField(draft.id, f.key, value),
|
||||||
'',
|
'',
|
||||||
)}
|
)}
|
||||||
|
{def.type === 'docker' && <DockerSetupHint baseUrl={draft.values.baseUrl ?? ''} />}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue