mirror of
https://github.com/docker/compose.git
synced 2025-07-20 12:14:41 +02:00
Add IPC support
Signed-off-by: aiordache <anca.iordache@docker.com>
This commit is contained in:
parent
9f81314124
commit
baeede2c6c
@ -100,7 +100,7 @@ func (s *composeService) Create(ctx context.Context, project *types.Project, opt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareNetworkMode(project)
|
prepareServicesDependsOn(project)
|
||||||
|
|
||||||
return InDependencyOrder(ctx, project, func(c context.Context, service types.ServiceConfig) error {
|
return InDependencyOrder(ctx, project, func(c context.Context, service types.ServiceConfig) error {
|
||||||
if utils.StringContains(opts.Services, service.Name) {
|
if utils.StringContains(opts.Services, service.Name) {
|
||||||
@ -142,18 +142,20 @@ func prepareNetworks(project *types.Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareNetworkMode(p *types.Project) {
|
func prepareServicesDependsOn(p *types.Project) {
|
||||||
outLoop:
|
outLoop:
|
||||||
for i := range p.Services {
|
for i := range p.Services {
|
||||||
dependency := getDependentServiceByNetwork(p.Services[i].NetworkMode)
|
networkDependency := getDependentServiceFromMode(p.Services[i].NetworkMode)
|
||||||
if dependency == "" {
|
ipcDependency := getDependentServiceFromMode(p.Services[i].Ipc)
|
||||||
|
|
||||||
|
if networkDependency == "" && ipcDependency == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if p.Services[i].DependsOn == nil {
|
if p.Services[i].DependsOn == nil {
|
||||||
p.Services[i].DependsOn = make(types.DependsOnConfig)
|
p.Services[i].DependsOn = make(types.DependsOnConfig)
|
||||||
}
|
}
|
||||||
for _, service := range p.Services {
|
for _, service := range p.Services {
|
||||||
if service.Name == dependency {
|
if service.Name == networkDependency || service.Name == ipcDependency {
|
||||||
p.Services[i].DependsOn[service.Name] = types.ServiceDependency{
|
p.Services[i].DependsOn[service.Name] = types.ServiceDependency{
|
||||||
Condition: types.ServiceConditionStarted,
|
Condition: types.ServiceConditionStarted,
|
||||||
}
|
}
|
||||||
@ -269,7 +271,14 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
|
|||||||
|
|
||||||
resources := getDeployResources(service)
|
resources := getDeployResources(service)
|
||||||
|
|
||||||
networkMode, err := getNetworkMode(ctx, p, service)
|
networkMode, err := getMode(ctx, service.Name, service.NetworkMode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
if networkMode == "" {
|
||||||
|
networkMode = getDefaultNetworkMode(p, service)
|
||||||
|
}
|
||||||
|
ipcmode, err := getMode(ctx, service.Name, service.Ipc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
@ -305,8 +314,9 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
|
|||||||
Mounts: mounts,
|
Mounts: mounts,
|
||||||
CapAdd: strslice.StrSlice(service.CapAdd),
|
CapAdd: strslice.StrSlice(service.CapAdd),
|
||||||
CapDrop: strslice.StrSlice(service.CapDrop),
|
CapDrop: strslice.StrSlice(service.CapDrop),
|
||||||
NetworkMode: networkMode,
|
NetworkMode: container.NetworkMode(networkMode),
|
||||||
Init: service.Init,
|
Init: service.Init,
|
||||||
|
IpcMode: container.IpcMode(ipcmode),
|
||||||
ReadonlyRootfs: service.ReadOnly,
|
ReadonlyRootfs: service.ReadOnly,
|
||||||
RestartPolicy: getRestartPolicy(service),
|
RestartPolicy: getRestartPolicy(service),
|
||||||
ShmSize: shmSize,
|
ShmSize: shmSize,
|
||||||
@ -328,10 +338,21 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
|
|||||||
LogConfig: logConfig,
|
LogConfig: logConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
networkConfig := buildDefaultNetworkConfig(service, networkMode, getContainerName(p.Name, service, number))
|
networkConfig := buildDefaultNetworkConfig(service, container.NetworkMode(networkMode), getContainerName(p.Name, service, number))
|
||||||
return &containerConfig, &hostConfig, networkConfig, nil
|
return &containerConfig, &hostConfig, networkConfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDefaultNetworkMode(project *types.Project, service types.ServiceConfig) string {
|
||||||
|
mode := "none"
|
||||||
|
if len(project.Networks) > 0 {
|
||||||
|
for name := range getNetworksForService(service) {
|
||||||
|
mode = project.Networks[name].Name
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mode
|
||||||
|
}
|
||||||
|
|
||||||
func getRestartPolicy(service types.ServiceConfig) container.RestartPolicy {
|
func getRestartPolicy(service types.ServiceConfig) container.RestartPolicy {
|
||||||
var restart container.RestartPolicy
|
var restart container.RestartPolicy
|
||||||
if service.Restart != "" {
|
if service.Restart != "" {
|
||||||
@ -470,12 +491,11 @@ func getVolumesFrom(project *types.Project, volumesFrom []string) ([]string, []s
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDependentServiceByNetwork(networkMode string) string {
|
func getDependentServiceFromMode(mode string) string {
|
||||||
baseService := ""
|
if strings.HasPrefix(mode, types.NetworkModeServicePrefix) {
|
||||||
if strings.HasPrefix(networkMode, types.NetworkModeServicePrefix) {
|
return mode[len(types.NetworkModeServicePrefix):]
|
||||||
return networkMode[len(types.NetworkModeServicePrefix):]
|
|
||||||
}
|
}
|
||||||
return baseService
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) buildContainerVolumes(ctx context.Context, p types.Project, service types.ServiceConfig,
|
func (s *composeService) buildContainerVolumes(ctx context.Context, p types.Project, service types.ServiceConfig,
|
||||||
@ -745,33 +765,22 @@ func getAliases(s types.ServiceConfig, c *types.ServiceNetworkConfig) []string {
|
|||||||
return aliases
|
return aliases
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNetworkMode(ctx context.Context, p *types.Project, service types.ServiceConfig) (container.NetworkMode, error) {
|
func getMode(ctx context.Context, serviceName string, mode string) (string, error) {
|
||||||
cState, err := GetContextContainerState(ctx)
|
cState, err := GetContextContainerState(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return container.NetworkMode("none"), nil
|
return "", nil
|
||||||
}
|
}
|
||||||
observedState := cState.GetContainers()
|
observedState := cState.GetContainers()
|
||||||
|
depService := getDependentServiceFromMode(mode)
|
||||||
mode := service.NetworkMode
|
if depService != "" {
|
||||||
if mode == "" {
|
depServiceContainers := observedState.filter(isService(depService))
|
||||||
if len(p.Networks) > 0 {
|
|
||||||
for name := range getNetworksForService(service) {
|
|
||||||
return container.NetworkMode(p.Networks[name].Name), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return container.NetworkMode("none"), nil
|
|
||||||
}
|
|
||||||
depServiceNetworkMode := getDependentServiceByNetwork(service.NetworkMode)
|
|
||||||
if depServiceNetworkMode != "" {
|
|
||||||
depServiceContainers := observedState.filter(isService(depServiceNetworkMode))
|
|
||||||
if len(depServiceContainers) > 0 {
|
if len(depServiceContainers) > 0 {
|
||||||
return container.NetworkMode(types.NetworkModeContainerPrefix + depServiceContainers[0].ID), nil
|
return types.NetworkModeContainerPrefix + depServiceContainers[0].ID, nil
|
||||||
}
|
}
|
||||||
return container.NetworkMode("none"),
|
return "", fmt.Errorf(`no containers started for %q in service %q -> %v`,
|
||||||
fmt.Errorf(`no containers started for network_mode %q in service %q -> %v`,
|
mode, serviceName, observedState)
|
||||||
mode, service.Name, observedState)
|
|
||||||
}
|
}
|
||||||
return container.NetworkMode(mode), nil
|
return mode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNetworksForService(s types.ServiceConfig) map[string]*types.ServiceNetworkConfig {
|
func getNetworksForService(s types.ServiceConfig) map[string]*types.ServiceNetworkConfig {
|
||||||
|
13
local/e2e/compose/fixtures/ipc-test/compose.yaml
Normal file
13
local/e2e/compose/fixtures/ipc-test/compose.yaml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
services:
|
||||||
|
service:
|
||||||
|
image: busybox
|
||||||
|
command: top
|
||||||
|
ipc: "service:shareable"
|
||||||
|
container:
|
||||||
|
image: busybox
|
||||||
|
command: top
|
||||||
|
ipc: "container:ipc_mode_container"
|
||||||
|
shareable:
|
||||||
|
image: busybox
|
||||||
|
command: top
|
||||||
|
ipc: shareable
|
65
local/e2e/compose/ipc_test.go
Normal file
65
local/e2e/compose/ipc_test.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 Docker Compose CLI authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package e2e
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gotest.tools/v3/icmd"
|
||||||
|
|
||||||
|
. "github.com/docker/compose-cli/utils/e2e"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIPC(t *testing.T) {
|
||||||
|
c := NewParallelE2eCLI(t, binDir)
|
||||||
|
|
||||||
|
const projectName = "ipc_e2e"
|
||||||
|
var cid string
|
||||||
|
t.Run("create ipc mode container", func(t *testing.T) {
|
||||||
|
res := c.RunDockerCmd("run", "-d", "--rm", "--ipc=shareable", "--name", "ipc_mode_container", "busybox", "top")
|
||||||
|
cid = strings.Trim(res.Stdout(), "\n")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("up", func(t *testing.T) {
|
||||||
|
c.RunDockerCmd("compose", "-f", "./fixtures/ipc-test/compose.yaml", "--project-name", projectName, "up", "-d")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("check running project", func(t *testing.T) {
|
||||||
|
res := c.RunDockerCmd("compose", "-p", projectName, "ps")
|
||||||
|
res.Assert(t, icmd.Expected{Out: `shareable`})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("check ipcmode in container inspect", func(t *testing.T) {
|
||||||
|
res := c.RunDockerCmd("inspect", projectName+"_shareable_1")
|
||||||
|
res.Assert(t, icmd.Expected{Out: `"IpcMode": "shareable",`})
|
||||||
|
|
||||||
|
res = c.RunDockerCmd("inspect", projectName+"_service_1")
|
||||||
|
res.Assert(t, icmd.Expected{Out: `"IpcMode": "container:`})
|
||||||
|
|
||||||
|
res = c.RunDockerCmd("inspect", projectName+"_container_1")
|
||||||
|
res.Assert(t, icmd.Expected{Out: fmt.Sprintf(`"IpcMode": "container:%s",`, cid)})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("down", func(t *testing.T) {
|
||||||
|
_ = c.RunDockerCmd("compose", "--project-name", projectName, "down")
|
||||||
|
})
|
||||||
|
t.Run("stop ipc mode container", func(t *testing.T) {
|
||||||
|
_ = c.RunDockerCmd("stop", "ipc_mode_container")
|
||||||
|
})
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user