mirror of
https://github.com/danbulant/docker-compose
synced 2026-06-20 23:21:29 +00:00
fix: fix mapping ipv6-based port mappings
This commit is contained in:
parent
963b51573f
commit
e7013dfab1
5 changed files with 91 additions and 57 deletions
31
src/index.ts
31
src/index.ts
|
|
@ -1,5 +1,7 @@
|
||||||
import childProcess from 'child_process'
|
import childProcess from 'child_process'
|
||||||
import yaml from 'yaml'
|
import yaml from 'yaml'
|
||||||
|
import mapPorts from './port-mapper'
|
||||||
|
|
||||||
export interface IDockerComposeOptions {
|
export interface IDockerComposeOptions {
|
||||||
cwd?: string
|
cwd?: string
|
||||||
executablePath?: string
|
executablePath?: string
|
||||||
|
|
@ -75,33 +77,6 @@ export type DockerComposePsResult = {
|
||||||
}>
|
}>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mapPorts = (
|
|
||||||
ports: string
|
|
||||||
): Array<{
|
|
||||||
mapped?: { address: string; port: number }
|
|
||||||
exposed: { port: number; protocol: string }
|
|
||||||
}> => {
|
|
||||||
const result = !ports
|
|
||||||
? []
|
|
||||||
: (() => {
|
|
||||||
return ports.split(',').map((untypedPort) => {
|
|
||||||
const exposedFragments = untypedPort.trim().split('->')
|
|
||||||
const [port, protocol] =
|
|
||||||
exposedFragments.length === 1
|
|
||||||
? exposedFragments[0].split('/')
|
|
||||||
: exposedFragments[1].split('/')
|
|
||||||
const [address, mappedPort] =
|
|
||||||
exposedFragments.length === 2 ? exposedFragments[0].split(':') : []
|
|
||||||
return {
|
|
||||||
exposed: { port: Number(port), protocol },
|
|
||||||
...(address &&
|
|
||||||
mappedPort && { mapped: { port: Number(mappedPort), address } })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})()
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
export const mapPsOutput = (output: string): DockerComposePsResult => {
|
export const mapPsOutput = (output: string): DockerComposePsResult => {
|
||||||
const services = output
|
const services = output
|
||||||
.split(`\n`)
|
.split(`\n`)
|
||||||
|
|
@ -514,3 +489,5 @@ export const version = async function (
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { mapPorts }
|
||||||
|
|
|
||||||
31
src/port-mapper.ts
Normal file
31
src/port-mapper.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
const mapPorts = (
|
||||||
|
ports: string
|
||||||
|
): Array<{
|
||||||
|
mapped?: { address: string; port: number }
|
||||||
|
exposed: { port: number; protocol: string }
|
||||||
|
}> => {
|
||||||
|
const result = !ports
|
||||||
|
? []
|
||||||
|
: (() => {
|
||||||
|
return ports.split(',').map((untypedPort) => {
|
||||||
|
const exposedFragments = untypedPort.trim().split('->')
|
||||||
|
|
||||||
|
console.log(exposedFragments)
|
||||||
|
|
||||||
|
const [port, protocol] =
|
||||||
|
exposedFragments.length === 1
|
||||||
|
? exposedFragments[0].split('/')
|
||||||
|
: exposedFragments[1].split('/')
|
||||||
|
const [address, mappedPort] =
|
||||||
|
exposedFragments.length === 2 ? exposedFragments[0].split(':') : []
|
||||||
|
return {
|
||||||
|
exposed: { port: Number(port), protocol },
|
||||||
|
...(address &&
|
||||||
|
mappedPort && { mapped: { port: Number(mappedPort), address } })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
export default mapPorts
|
||||||
|
|
@ -6,8 +6,8 @@ services:
|
||||||
container_name: compose_test_web
|
container_name: compose_test_web
|
||||||
command: 'nginx -g "daemon off;"'
|
command: 'nginx -g "daemon off;"'
|
||||||
ports:
|
ports:
|
||||||
- 80:80
|
- '0.0.0.0:80:80'
|
||||||
- 443:443
|
- '0.0.0.0:443:443'
|
||||||
proxy:
|
proxy:
|
||||||
image: nginx:1.19.9-alpine
|
image: nginx:1.19.9-alpine
|
||||||
container_name: compose_test_proxy
|
container_name: compose_test_proxy
|
||||||
|
|
|
||||||
|
|
@ -699,31 +699,3 @@ test('parse ps output', () => {
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('map ports', () => {
|
|
||||||
const noPort = ''
|
|
||||||
const exposedTcp = '80/tcp'
|
|
||||||
const mappedExposedTcp = '0.0.0.0:443->443/tcp'
|
|
||||||
const multipleExposedMappedTcp = '0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp'
|
|
||||||
|
|
||||||
expect(mapPorts(noPort)).toEqual([])
|
|
||||||
expect(mapPorts(exposedTcp)).toEqual([
|
|
||||||
{ exposed: { port: 80, protocol: 'tcp' } }
|
|
||||||
])
|
|
||||||
expect(mapPorts(mappedExposedTcp)).toEqual([
|
|
||||||
{
|
|
||||||
exposed: { port: 443, protocol: 'tcp' },
|
|
||||||
mapped: { address: '0.0.0.0', port: 443 }
|
|
||||||
}
|
|
||||||
])
|
|
||||||
expect(mapPorts(multipleExposedMappedTcp)).toEqual([
|
|
||||||
{
|
|
||||||
exposed: { port: 443, protocol: 'tcp' },
|
|
||||||
mapped: { address: '0.0.0.0', port: 443 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
exposed: { port: 80, protocol: 'tcp' },
|
|
||||||
mapped: { address: '0.0.0.0', port: 80 }
|
|
||||||
}
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
|
||||||
54
test/port-mapper.test.ts
Normal file
54
test/port-mapper.test.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
import mapPorts from "../src/port-mapper";
|
||||||
|
|
||||||
|
test('map ports for empty string', () => {
|
||||||
|
expect(mapPorts('')).toEqual([])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('map ports for exposed tcp', () => {
|
||||||
|
expect(mapPorts('80/tcp')).toEqual([
|
||||||
|
{ exposed: { port: 80, protocol: 'tcp' } }
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('map ports for exposed tcp on ivp4 interface', () => {
|
||||||
|
expect(mapPorts('0.0.0.0:443->443/tcp')).toEqual([
|
||||||
|
{
|
||||||
|
exposed: { port: 443, protocol: 'tcp' },
|
||||||
|
mapped: { address: '0.0.0.0', port: 443 }
|
||||||
|
}
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('map multiple tcp ports exposed on ivp4 interfaces', () => {
|
||||||
|
expect(mapPorts('0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp')).toEqual([
|
||||||
|
{
|
||||||
|
exposed: { port: 443, protocol: 'tcp' },
|
||||||
|
mapped: { address: '0.0.0.0', port: 443 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
exposed: { port: 80, protocol: 'tcp' },
|
||||||
|
mapped: { address: '0.0.0.0', port: 80 }
|
||||||
|
}
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('map multiple tcp ports exposed on ipv4 and ipv6 interfaces', () => {
|
||||||
|
expect(mapPorts('0.0.0.0:443->443/tcp,:::443->443/tcp, 0.0.0.0:80->80/tcp,:::80->80/tcp')).toEqual([
|
||||||
|
{
|
||||||
|
exposed: { port: 443, protocol: 'tcp' },
|
||||||
|
mapped: { address: '0.0.0.0', port: 443 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
exposed: { port: 443, protocol: 'tcp' },
|
||||||
|
mapped: { address: ':::', port: 443 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
exposed: { port: 80, protocol: 'tcp' },
|
||||||
|
mapped: { address: '0.0.0.0', port: 80 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
exposed: { port: 80, protocol: 'tcp' },
|
||||||
|
mapped: { address: ':::', port: 80 },
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
Loading…
Reference in a new issue