diff --git a/Sources/ContainerResource/Container/Bundle.swift b/Sources/ContainerResource/Container/Bundle.swift index 28f67cca..217531b8 100644 --- a/Sources/ContainerResource/Container/Bundle.swift +++ b/Sources/ContainerResource/Container/Bundle.swift @@ -110,9 +110,11 @@ extension Bundle { try bundle.write(filename: Self.containerConfigFilename, value: containerConfiguration) } - if let containerRootFilesystem { + if let rootFsOverride = options?.rootFsOverride { + try bundle.setContainerRootFs(fs: rootFsOverride) + } else if let containerRootFilesystem { let readonly = containerConfiguration?.readOnly ?? false - try bundle.setContainerRootFs(cloning: containerRootFilesystem, readonly: readonly) + try bundle.cloneContainerRootFs(cloning: containerRootFilesystem, readonly: readonly) } if let options { @@ -133,14 +135,18 @@ extension Bundle { path.appendingPathComponent(name) } - public func setContainerRootFs(cloning fs: Filesystem, readonly: Bool = false) throws { + public func setContainerRootFs(fs: Filesystem) throws { + let fsData = try JSONEncoder().encode(fs) + try fsData.write(to: self.containerRootfsConfig) + } + + public func cloneContainerRootFs(cloning fs: Filesystem, readonly: Bool = false) throws { var mutableFs = fs if readonly && !mutableFs.options.contains("ro") { mutableFs.options.append("ro") } let cloned = try mutableFs.clone(to: self.containerRootfsBlock.absolutePath()) - let fsData = try JSONEncoder().encode(cloned) - try fsData.write(to: self.containerRootfsConfig) + try setContainerRootFs(fs: cloned) } /// Delete the bundle and all of the resources contained inside. diff --git a/Sources/ContainerResource/Container/ContainerCreateOptions.swift b/Sources/ContainerResource/Container/ContainerCreateOptions.swift index dd9da217..fe75577b 100644 --- a/Sources/ContainerResource/Container/ContainerCreateOptions.swift +++ b/Sources/ContainerResource/Container/ContainerCreateOptions.swift @@ -15,10 +15,14 @@ //===----------------------------------------------------------------------===// public struct ContainerCreateOptions: Codable, Sendable { + /// Remove the container and wipe out its data on container stop public let autoRemove: Bool + /// Override the rootFs with this one other than the image-cloned version + public let rootFsOverride: Filesystem? - public init(autoRemove: Bool) { + public init(autoRemove: Bool, rootFsOverride: Filesystem? = nil) { self.autoRemove = autoRemove + self.rootFsOverride = rootFsOverride } public static let `default` = ContainerCreateOptions(autoRemove: false) diff --git a/Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift b/Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift index b266116f..b1ea7981 100644 --- a/Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift +++ b/Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift @@ -364,7 +364,7 @@ public actor ContainersService { "ref": "\(configuration.image.reference)", ]) let containerImage = ClientImage(description: configuration.image) - let imageFs = try await containerImage.getCreateSnapshot(platform: configuration.platform) + let imageFs = try await options.rootFsOverride == nil ? containerImage.getCreateSnapshot(platform: configuration.platform) : nil self.log.debug( "configure runtime",