@@ -8,13 +8,16 @@ import (
88 "log"
99 "strconv"
1010 "strings"
11+ "sync"
1112 "time"
1213
14+ dockertypes "github.com/docker/docker/api/types"
1315 "github.com/docker/docker/api/types/container"
1416 "github.com/docker/docker/api/types/filters"
1517 "github.com/docker/docker/client"
1618 "github.com/docker/docker/pkg/stdcopy"
1719 "github.com/docker/go-connections/nat"
20+ "golang.org/x/sync/errgroup"
1821)
1922
2023// Local Container Service.
@@ -23,70 +26,51 @@ type containerService struct {
2326}
2427
2528func (s * containerService ) List (ctx context.Context ) ([]Container , error ) {
26- log .Printf ("[docker] ContainerList: all=true" )
27- containers , listErr := s .cli .ContainerList (ctx , container.ListOptions {All : true })
28- if listErr != nil {
29- return nil , listErr
29+ log .Printf ("[docker] ContainerList" )
30+ du , err := s .cli .DiskUsage (ctx , dockertypes.DiskUsageOptions {
31+ Types : []dockertypes.DiskUsageObject {dockertypes .ContainerObject },
32+ })
33+
34+ if err != nil {
35+ return nil , err
3036 }
3137
38+ containers := du .Containers
39+
3240 result := make ([]Container , len (containers ))
41+ resultMap := sync.Map {}
42+ group , groupCtx := errgroup .WithContext (ctx )
43+ group .SetLimit (parallelInspectLimit )
44+
3345 for i , c := range containers {
34- name := ""
35- if len (c .Names ) > 0 {
36- name = strings .TrimPrefix (c .Names [0 ], "/" )
37- }
46+ idx := i
3847
39- state := StateStopped
40- switch c .State {
41- case "running" :
42- state = StateRunning
43- case "paused" :
44- state = StatePaused
45- case "restarting" :
46- state = StateRestarting
47- }
48+ group .Go (func () error {
49+ container , containerErr := s .Get (groupCtx , c .ID )
4850
49- ports := make ([]PortMapping , 0 )
50- for _ , p := range c .Ports {
51- if p .PublicPort > 0 {
52- ports = append (ports , PortMapping {
53- HostPort : p .PublicPort ,
54- ContainerPort : p .PrivatePort ,
55- Protocol : p .Type ,
56- })
51+ if containerErr != nil {
52+ return containerErr
5753 }
58- }
5954
60- mounts := make ([]Mount , len (c .Mounts ))
61- for j , m := range c .Mounts {
62- mounts [j ] = Mount {
63- Type : string (m .Type ),
64- Source : m .Source ,
65- Destination : m .Destination ,
66- }
67- }
55+ resultMap .Store (idx , container )
6856
69- ci , err := s .cli .ContainerInspect (ctx , c .ID )
70- if err != nil {
71- return nil , err
72- }
57+ return nil
58+ })
59+ }
7360
74- health := buildContainerHealth (ci .State .Health )
75-
76- result [i ] = Container {
77- ID : c .ID ,
78- Name : name ,
79- Image : c .Image ,
80- Status : c .Status ,
81- State : state ,
82- Health : health ,
83- Created : timeFromUnix (c .Created ),
84- Ports : ports ,
85- Mounts : mounts ,
86- }
61+ groupErr := group .Wait ()
62+ if groupErr != nil {
63+ return nil , groupErr
8764 }
8865
89- log .Printf ("[docker] ContainerList: returned count=%d err=%v" , len (result ), listErr )
66+ resultMap .Range (func (key , value any ) bool {
67+ idx , _ := key .(int )
68+ c , _ := value .(Container )
69+ result [idx ] = c
70+ return true
71+ })
72+
73+ log .Printf ("[docker] ContainerList: returned count=%d err=%v" , len (result ), err )
9074 return result , nil
9175}
9276
@@ -172,11 +156,11 @@ func (s *containerService) Run(ctx context.Context, img Image, opts RunOptions)
172156 return containerResponse .ID , nil
173157}
174158
175- func (s * containerService ) Get (ctx context.Context , id string ) (* Container , error ) {
159+ func (s * containerService ) Get (ctx context.Context , id string ) (Container , error ) {
176160 log .Printf ("[docker] ContainerInspect: id=%q" , id )
177161 c , err := s .cli .ContainerInspect (ctx , id )
178162 if err != nil {
179- return nil , err
163+ return Container {} , err
180164 }
181165
182166 state := StateStopped
@@ -192,7 +176,7 @@ func (s *containerService) Get(ctx context.Context, id string) (*Container, erro
192176 var created time.Time
193177 created , err = time .Parse (time .RFC3339Nano , c .Created )
194178 if err != nil {
195- return nil , fmt .Errorf ("parsing container created time: %w" , err )
179+ return Container {} , fmt .Errorf ("parsing container created time: %w" , err )
196180 }
197181
198182 ports := make ([]PortMapping , 0 )
@@ -241,7 +225,7 @@ func (s *containerService) Get(ctx context.Context, id string) (*Container, erro
241225 }
242226
243227 log .Printf ("[docker] ContainerInspect: done" )
244- return & Container {
228+ return Container {
245229 ID : c .ID ,
246230 Name : strings .TrimPrefix (c .Name , "/" ),
247231 Image : c .Config .Image ,
0 commit comments