@@ -35,14 +35,31 @@ import (
35
35
"github.com/containerd/nerdctl/v2/pkg/composer/serviceparser"
36
36
"github.com/containerd/nerdctl/v2/pkg/imgutil"
37
37
"github.com/containerd/nerdctl/v2/pkg/ipfs"
38
+ "github.com/containerd/nerdctl/v2/pkg/lockutil"
38
39
"github.com/containerd/nerdctl/v2/pkg/netutil"
39
40
"github.com/containerd/nerdctl/v2/pkg/referenceutil"
40
41
"github.com/containerd/nerdctl/v2/pkg/signutil"
41
42
"github.com/containerd/nerdctl/v2/pkg/strutil"
42
43
)
43
44
45
+ //nolint:unused
46
+ var locked * os.File
47
+
44
48
// New returns a new *composer.Composer.
45
49
func New (client * containerd.Client , globalOptions types.GlobalCommandOptions , options composer.Options , stdout , stderr io.Writer ) (* composer.Composer , error ) {
50
+ // Compose right now cannot be made safe to use concurrently, as we shell out to nerdctl for multiple operations,
51
+ // preventing us from using the lock mechanisms from the API.
52
+ // This here imposes a global lock, effectively preventing multiple compose commands from being run in parallel and
53
+ // preventing some of the problems with concurrent execution.
54
+ // This should be removed once we have better, in-depth solutions to make this concurrency safe.
55
+ // Note that we do not close the lock explicitly. Instead, the lock will get released when the `locked` global
56
+ // variable will get collected and the file descriptor closed (eg: when the binary exits).
57
+ var err error
58
+ locked , err = lockutil .Lock (globalOptions .DataRoot )
59
+ if err != nil {
60
+ return nil , err
61
+ }
62
+
46
63
cniEnv , err := netutil .NewCNIEnv (globalOptions .CNIPath , globalOptions .CNINetConfPath , netutil .WithNamespace (globalOptions .Namespace ), netutil .WithDefaultNetwork ())
47
64
if err != nil {
48
65
return nil , err
0 commit comments