github.com/google/osv-scalibr@v0.4.1/extractor/standalone/containers/docker/docker.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package docker extracts container inventory from docker API. 16 package docker 17 18 import ( 19 "context" 20 "fmt" 21 22 "github.com/docker/docker/api/types/container" 23 "github.com/docker/docker/client" 24 "github.com/google/osv-scalibr/extractor" 25 "github.com/google/osv-scalibr/extractor/standalone" 26 "github.com/google/osv-scalibr/inventory" 27 "github.com/google/osv-scalibr/plugin" 28 ) 29 30 const ( 31 // Name is the unique name of this extractor. 32 Name = "containers/docker" 33 ) 34 35 // Extractor implements the docker extractor. 36 type Extractor struct { 37 client Client 38 } 39 40 // New returns an extractor 41 func New() standalone.Extractor { 42 return &Extractor{} 43 } 44 45 // NewWithClient returns an extractor which uses a specified docker client. 46 func NewWithClient(c Client) standalone.Extractor { 47 return &Extractor{client: c} 48 } 49 50 // Name of the extractor. 51 func (e Extractor) Name() string { return Name } 52 53 // Version of the extractor. 54 func (e Extractor) Version() int { return 0 } 55 56 // Requirements of the extractor. 57 func (e Extractor) Requirements() *plugin.Capabilities { 58 return &plugin.Capabilities{RunningSystem: true} 59 } 60 61 // Extract extracts containers from the docker API. 62 func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) (inventory.Inventory, error) { 63 if e.client == nil { 64 var err error 65 e.client, err = client.NewClientWithOpts(client.WithAPIVersionNegotiation()) 66 if err != nil { 67 return inventory.Inventory{}, fmt.Errorf("cannot connect with docker %w", err) 68 } 69 } 70 71 // extract running containers 72 containers, err := e.client.ContainerList(ctx, container.ListOptions{}) 73 if err != nil { 74 return inventory.Inventory{}, fmt.Errorf("error fetching containers: %w", err) 75 } 76 77 pkgs := make([]*extractor.Package, 0, len(containers)) 78 for _, ctr := range containers { 79 pkgs = append(pkgs, &extractor.Package{ 80 Name: ctr.Image, 81 Version: ctr.ImageID, 82 Metadata: &Metadata{ 83 ImageName: ctr.Image, 84 ImageDigest: ctr.ImageID, 85 ID: ctr.ID, 86 Ports: ctr.Ports, 87 }, 88 }) 89 } 90 return inventory.Inventory{Packages: pkgs}, nil 91 }