server.go 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392
  1. package docker
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "github.com/dotcloud/docker/archive"
  7. "github.com/dotcloud/docker/auth"
  8. "github.com/dotcloud/docker/engine"
  9. "github.com/dotcloud/docker/pkg/cgroups"
  10. "github.com/dotcloud/docker/pkg/graphdb"
  11. "github.com/dotcloud/docker/registry"
  12. "github.com/dotcloud/docker/utils"
  13. "io"
  14. "io/ioutil"
  15. "log"
  16. "net/http"
  17. "net/url"
  18. "os"
  19. "os/exec"
  20. "os/signal"
  21. "path"
  22. "path/filepath"
  23. "runtime"
  24. "strconv"
  25. "strings"
  26. "sync"
  27. "syscall"
  28. "time"
  29. )
  30. func (srv *Server) Close() error {
  31. return srv.runtime.Close()
  32. }
  33. func init() {
  34. engine.Register("initapi", jobInitApi)
  35. }
  36. // jobInitApi runs the remote api server `srv` as a daemon,
  37. // Only one api server can run at the same time - this is enforced by a pidfile.
  38. // The signals SIGINT, SIGQUIT and SIGTERM are intercepted for cleanup.
  39. func jobInitApi(job *engine.Job) engine.Status {
  40. job.Logf("Creating server")
  41. // FIXME: ImportEnv deprecates ConfigFromJob
  42. srv, err := NewServer(job.Eng, ConfigFromJob(job))
  43. if err != nil {
  44. job.Error(err)
  45. return engine.StatusErr
  46. }
  47. if srv.runtime.config.Pidfile != "" {
  48. job.Logf("Creating pidfile")
  49. if err := utils.CreatePidFile(srv.runtime.config.Pidfile); err != nil {
  50. // FIXME: do we need fatal here instead of returning a job error?
  51. log.Fatal(err)
  52. }
  53. }
  54. job.Logf("Setting up signal traps")
  55. c := make(chan os.Signal, 1)
  56. signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
  57. go func() {
  58. sig := <-c
  59. log.Printf("Received signal '%v', exiting\n", sig)
  60. utils.RemovePidFile(srv.runtime.config.Pidfile)
  61. srv.Close()
  62. os.Exit(0)
  63. }()
  64. job.Eng.Hack_SetGlobalVar("httpapi.server", srv)
  65. job.Eng.Hack_SetGlobalVar("httpapi.runtime", srv.runtime)
  66. // https://github.com/dotcloud/docker/issues/2768
  67. if srv.runtime.networkManager.bridgeNetwork != nil {
  68. job.Eng.Hack_SetGlobalVar("httpapi.bridgeIP", srv.runtime.networkManager.bridgeNetwork.IP)
  69. }
  70. for name, handler := range map[string]engine.Handler{
  71. "export": srv.ContainerExport,
  72. "create": srv.ContainerCreate,
  73. "stop": srv.ContainerStop,
  74. "restart": srv.ContainerRestart,
  75. "start": srv.ContainerStart,
  76. "kill": srv.ContainerKill,
  77. "serveapi": srv.ListenAndServe,
  78. "wait": srv.ContainerWait,
  79. "tag": srv.ImageTag,
  80. "resize": srv.ContainerResize,
  81. "commit": srv.ContainerCommit,
  82. "info": srv.DockerInfo,
  83. "container_delete": srv.ContainerDestroy,
  84. "image_export": srv.ImageExport,
  85. "images": srv.Images,
  86. "history": srv.ImageHistory,
  87. "viz": srv.ImagesViz,
  88. "container_copy": srv.ContainerCopy,
  89. "insert": srv.ImageInsert,
  90. "attach": srv.ContainerAttach,
  91. "search": srv.ImagesSearch,
  92. "changes": srv.ContainerChanges,
  93. "top": srv.ContainerTop,
  94. "load": srv.ImageLoad,
  95. "build": srv.Build,
  96. "pull": srv.ImagePull,
  97. "import": srv.ImageImport,
  98. } {
  99. if err := job.Eng.Register(name, handler); err != nil {
  100. job.Error(err)
  101. return engine.StatusErr
  102. }
  103. }
  104. return engine.StatusOK
  105. }
  106. func (srv *Server) ListenAndServe(job *engine.Job) engine.Status {
  107. protoAddrs := job.Args
  108. chErrors := make(chan error, len(protoAddrs))
  109. for _, protoAddr := range protoAddrs {
  110. protoAddrParts := strings.SplitN(protoAddr, "://", 2)
  111. switch protoAddrParts[0] {
  112. case "unix":
  113. if err := syscall.Unlink(protoAddrParts[1]); err != nil && !os.IsNotExist(err) {
  114. log.Fatal(err)
  115. }
  116. case "tcp":
  117. if !strings.HasPrefix(protoAddrParts[1], "127.0.0.1") {
  118. log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
  119. }
  120. default:
  121. job.Errorf("Invalid protocol format.")
  122. return engine.StatusErr
  123. }
  124. go func() {
  125. // FIXME: merge Server.ListenAndServe with ListenAndServe
  126. chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], srv, job.GetenvBool("Logging"))
  127. }()
  128. }
  129. for i := 0; i < len(protoAddrs); i += 1 {
  130. err := <-chErrors
  131. if err != nil {
  132. job.Error(err)
  133. return engine.StatusErr
  134. }
  135. }
  136. return engine.StatusOK
  137. }
  138. // simpleVersionInfo is a simple implementation of
  139. // the interface VersionInfo, which is used
  140. // to provide version information for some product,
  141. // component, etc. It stores the product name and the version
  142. // in string and returns them on calls to Name() and Version().
  143. type simpleVersionInfo struct {
  144. name string
  145. version string
  146. }
  147. func (v *simpleVersionInfo) Name() string {
  148. return v.name
  149. }
  150. func (v *simpleVersionInfo) Version() string {
  151. return v.version
  152. }
  153. // ContainerKill send signal to the container
  154. // If no signal is given (sig 0), then Kill with SIGKILL and wait
  155. // for the container to exit.
  156. // If a signal is given, then just send it to the container and return.
  157. func (srv *Server) ContainerKill(job *engine.Job) engine.Status {
  158. signalMap := map[string]syscall.Signal{
  159. "HUP": syscall.SIGHUP,
  160. "INT": syscall.SIGINT,
  161. "QUIT": syscall.SIGQUIT,
  162. "ILL": syscall.SIGILL,
  163. "TRAP": syscall.SIGTRAP,
  164. "ABRT": syscall.SIGABRT,
  165. "BUS": syscall.SIGBUS,
  166. "FPE": syscall.SIGFPE,
  167. "KILL": syscall.SIGKILL,
  168. "USR1": syscall.SIGUSR1,
  169. "SEGV": syscall.SIGSEGV,
  170. "USR2": syscall.SIGUSR2,
  171. "PIPE": syscall.SIGPIPE,
  172. "ALRM": syscall.SIGALRM,
  173. "TERM": syscall.SIGTERM,
  174. //"STKFLT": syscall.SIGSTKFLT,
  175. "CHLD": syscall.SIGCHLD,
  176. "CONT": syscall.SIGCONT,
  177. "STOP": syscall.SIGSTOP,
  178. "TSTP": syscall.SIGTSTP,
  179. "TTIN": syscall.SIGTTIN,
  180. "TTOU": syscall.SIGTTOU,
  181. "URG": syscall.SIGURG,
  182. "XCPU": syscall.SIGXCPU,
  183. "XFSZ": syscall.SIGXFSZ,
  184. "VTALRM": syscall.SIGVTALRM,
  185. "PROF": syscall.SIGPROF,
  186. "WINCH": syscall.SIGWINCH,
  187. "IO": syscall.SIGIO,
  188. //"PWR": syscall.SIGPWR,
  189. "SYS": syscall.SIGSYS,
  190. }
  191. if n := len(job.Args); n < 1 || n > 2 {
  192. job.Errorf("Usage: %s CONTAINER [SIGNAL]", job.Name)
  193. return engine.StatusErr
  194. }
  195. name := job.Args[0]
  196. var sig uint64
  197. if len(job.Args) == 2 && job.Args[1] != "" {
  198. sig = uint64(signalMap[job.Args[1]])
  199. if sig == 0 {
  200. var err error
  201. // The largest legal signal is 31, so let's parse on 5 bits
  202. sig, err = strconv.ParseUint(job.Args[1], 10, 5)
  203. if err != nil {
  204. job.Errorf("Invalid signal: %s", job.Args[1])
  205. return engine.StatusErr
  206. }
  207. }
  208. }
  209. if container := srv.runtime.Get(name); container != nil {
  210. // If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait())
  211. if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
  212. if err := container.Kill(); err != nil {
  213. job.Errorf("Cannot kill container %s: %s", name, err)
  214. return engine.StatusErr
  215. }
  216. srv.LogEvent("kill", container.ID, srv.runtime.repositories.ImageName(container.Image))
  217. } else {
  218. // Otherwise, just send the requested signal
  219. if err := container.kill(int(sig)); err != nil {
  220. job.Errorf("Cannot kill container %s: %s", name, err)
  221. return engine.StatusErr
  222. }
  223. // FIXME: Add event for signals
  224. }
  225. } else {
  226. job.Errorf("No such container: %s", name)
  227. return engine.StatusErr
  228. }
  229. return engine.StatusOK
  230. }
  231. func (srv *Server) ContainerExport(job *engine.Job) engine.Status {
  232. if len(job.Args) != 1 {
  233. job.Errorf("Usage: %s container_id", job.Name)
  234. return engine.StatusErr
  235. }
  236. name := job.Args[0]
  237. if container := srv.runtime.Get(name); container != nil {
  238. data, err := container.Export()
  239. if err != nil {
  240. job.Errorf("%s: %s", name, err)
  241. return engine.StatusErr
  242. }
  243. // Stream the entire contents of the container (basically a volatile snapshot)
  244. if _, err := io.Copy(job.Stdout, data); err != nil {
  245. job.Errorf("%s: %s", name, err)
  246. return engine.StatusErr
  247. }
  248. // FIXME: factor job-specific LogEvent to engine.Job.Run()
  249. srv.LogEvent("export", container.ID, srv.runtime.repositories.ImageName(container.Image))
  250. return engine.StatusOK
  251. }
  252. job.Errorf("No such container: %s", name)
  253. return engine.StatusErr
  254. }
  255. // ImageExport exports all images with the given tag. All versions
  256. // containing the same tag are exported. The resulting output is an
  257. // uncompressed tar ball.
  258. // name is the set of tags to export.
  259. // out is the writer where the images are written to.
  260. func (srv *Server) ImageExport(job *engine.Job) engine.Status {
  261. if len(job.Args) != 1 {
  262. job.Errorf("Usage: %s CONTAINER\n", job.Name)
  263. return engine.StatusErr
  264. }
  265. name := job.Args[0]
  266. // get image json
  267. tempdir, err := ioutil.TempDir("", "docker-export-")
  268. if err != nil {
  269. job.Error(err)
  270. return engine.StatusErr
  271. }
  272. defer os.RemoveAll(tempdir)
  273. utils.Debugf("Serializing %s", name)
  274. rootRepo, err := srv.runtime.repositories.Get(name)
  275. if err != nil {
  276. job.Error(err)
  277. return engine.StatusErr
  278. }
  279. if rootRepo != nil {
  280. for _, id := range rootRepo {
  281. image, err := srv.ImageInspect(id)
  282. if err != nil {
  283. job.Error(err)
  284. return engine.StatusErr
  285. }
  286. if err := srv.exportImage(image, tempdir); err != nil {
  287. job.Error(err)
  288. return engine.StatusErr
  289. }
  290. }
  291. // write repositories
  292. rootRepoMap := map[string]Repository{}
  293. rootRepoMap[name] = rootRepo
  294. rootRepoJson, _ := json.Marshal(rootRepoMap)
  295. if err := ioutil.WriteFile(path.Join(tempdir, "repositories"), rootRepoJson, os.ModeAppend); err != nil {
  296. job.Error(err)
  297. return engine.StatusErr
  298. }
  299. } else {
  300. image, err := srv.ImageInspect(name)
  301. if err != nil {
  302. job.Error(err)
  303. return engine.StatusErr
  304. }
  305. if err := srv.exportImage(image, tempdir); err != nil {
  306. job.Error(err)
  307. return engine.StatusErr
  308. }
  309. }
  310. fs, err := archive.Tar(tempdir, archive.Uncompressed)
  311. if err != nil {
  312. job.Error(err)
  313. return engine.StatusErr
  314. }
  315. if _, err := io.Copy(job.Stdout, fs); err != nil {
  316. job.Error(err)
  317. return engine.StatusErr
  318. }
  319. return engine.StatusOK
  320. }
  321. func (srv *Server) exportImage(image *Image, tempdir string) error {
  322. for i := image; i != nil; {
  323. // temporary directory
  324. tmpImageDir := path.Join(tempdir, i.ID)
  325. if err := os.Mkdir(tmpImageDir, os.ModeDir); err != nil {
  326. if os.IsExist(err) {
  327. return nil
  328. }
  329. return err
  330. }
  331. var version = "1.0"
  332. var versionBuf = []byte(version)
  333. if err := ioutil.WriteFile(path.Join(tmpImageDir, "VERSION"), versionBuf, os.ModeAppend); err != nil {
  334. return err
  335. }
  336. // serialize json
  337. b, err := json.Marshal(i)
  338. if err != nil {
  339. return err
  340. }
  341. if err := ioutil.WriteFile(path.Join(tmpImageDir, "json"), b, os.ModeAppend); err != nil {
  342. return err
  343. }
  344. // serialize filesystem
  345. fs, err := i.TarLayer()
  346. if err != nil {
  347. return err
  348. }
  349. fsTar, err := os.Create(path.Join(tmpImageDir, "layer.tar"))
  350. if err != nil {
  351. return err
  352. }
  353. if _, err = io.Copy(fsTar, fs); err != nil {
  354. return err
  355. }
  356. fsTar.Close()
  357. // find parent
  358. if i.Parent != "" {
  359. i, err = srv.ImageInspect(i.Parent)
  360. if err != nil {
  361. return err
  362. }
  363. } else {
  364. i = nil
  365. }
  366. }
  367. return nil
  368. }
  369. func (srv *Server) Build(job *engine.Job) engine.Status {
  370. if len(job.Args) != 0 {
  371. job.Errorf("Usage: %s\n", job.Name)
  372. return engine.StatusErr
  373. }
  374. var (
  375. remoteURL = job.Getenv("remote")
  376. repoName = job.Getenv("t")
  377. suppressOutput = job.GetenvBool("q")
  378. noCache = job.GetenvBool("nocache")
  379. rm = job.GetenvBool("rm")
  380. authConfig = &auth.AuthConfig{}
  381. configFile = &auth.ConfigFile{}
  382. tag string
  383. context io.Reader
  384. )
  385. job.GetenvJson("authConfig", authConfig)
  386. job.GetenvJson("configFile", configFile)
  387. repoName, tag = utils.ParseRepositoryTag(repoName)
  388. if remoteURL == "" {
  389. context = job.Stdin
  390. } else if utils.IsGIT(remoteURL) {
  391. if !strings.HasPrefix(remoteURL, "git://") {
  392. remoteURL = "https://" + remoteURL
  393. }
  394. root, err := ioutil.TempDir("", "docker-build-git")
  395. if err != nil {
  396. job.Error(err)
  397. return engine.StatusErr
  398. }
  399. defer os.RemoveAll(root)
  400. if output, err := exec.Command("git", "clone", remoteURL, root).CombinedOutput(); err != nil {
  401. job.Errorf("Error trying to use git: %s (%s)", err, output)
  402. return engine.StatusErr
  403. }
  404. c, err := archive.Tar(root, archive.Uncompressed)
  405. if err != nil {
  406. job.Error(err)
  407. return engine.StatusErr
  408. }
  409. context = c
  410. } else if utils.IsURL(remoteURL) {
  411. f, err := utils.Download(remoteURL)
  412. if err != nil {
  413. job.Error(err)
  414. return engine.StatusErr
  415. }
  416. defer f.Body.Close()
  417. dockerFile, err := ioutil.ReadAll(f.Body)
  418. if err != nil {
  419. job.Error(err)
  420. return engine.StatusErr
  421. }
  422. c, err := MkBuildContext(string(dockerFile), nil)
  423. if err != nil {
  424. job.Error(err)
  425. return engine.StatusErr
  426. }
  427. context = c
  428. }
  429. sf := utils.NewStreamFormatter(job.GetenvBool("json"))
  430. b := NewBuildFile(srv,
  431. &StdoutFormater{
  432. Writer: job.Stdout,
  433. StreamFormatter: sf,
  434. },
  435. &StderrFormater{
  436. Writer: job.Stdout,
  437. StreamFormatter: sf,
  438. },
  439. !suppressOutput, !noCache, rm, job.Stdout, sf, authConfig, configFile)
  440. id, err := b.Build(context)
  441. if err != nil {
  442. job.Error(err)
  443. return engine.StatusErr
  444. }
  445. if repoName != "" {
  446. srv.runtime.repositories.Set(repoName, tag, id, false)
  447. }
  448. return engine.StatusOK
  449. }
  450. // Loads a set of images into the repository. This is the complementary of ImageExport.
  451. // The input stream is an uncompressed tar ball containing images and metadata.
  452. func (srv *Server) ImageLoad(job *engine.Job) engine.Status {
  453. tmpImageDir, err := ioutil.TempDir("", "docker-import-")
  454. if err != nil {
  455. job.Error(err)
  456. return engine.StatusErr
  457. }
  458. defer os.RemoveAll(tmpImageDir)
  459. var (
  460. repoTarFile = path.Join(tmpImageDir, "repo.tar")
  461. repoDir = path.Join(tmpImageDir, "repo")
  462. )
  463. tarFile, err := os.Create(repoTarFile)
  464. if err != nil {
  465. job.Error(err)
  466. return engine.StatusErr
  467. }
  468. if _, err := io.Copy(tarFile, job.Stdin); err != nil {
  469. job.Error(err)
  470. return engine.StatusErr
  471. }
  472. tarFile.Close()
  473. repoFile, err := os.Open(repoTarFile)
  474. if err != nil {
  475. job.Error(err)
  476. return engine.StatusErr
  477. }
  478. if err := os.Mkdir(repoDir, os.ModeDir); err != nil {
  479. job.Error(err)
  480. return engine.StatusErr
  481. }
  482. if err := archive.Untar(repoFile, repoDir, nil); err != nil {
  483. job.Error(err)
  484. return engine.StatusErr
  485. }
  486. dirs, err := ioutil.ReadDir(repoDir)
  487. if err != nil {
  488. job.Error(err)
  489. return engine.StatusErr
  490. }
  491. for _, d := range dirs {
  492. if d.IsDir() {
  493. if err := srv.recursiveLoad(d.Name(), tmpImageDir); err != nil {
  494. job.Error(err)
  495. return engine.StatusErr
  496. }
  497. }
  498. }
  499. repositoriesJson, err := ioutil.ReadFile(path.Join(tmpImageDir, "repo", "repositories"))
  500. if err == nil {
  501. repositories := map[string]Repository{}
  502. if err := json.Unmarshal(repositoriesJson, &repositories); err != nil {
  503. job.Error(err)
  504. return engine.StatusErr
  505. }
  506. for imageName, tagMap := range repositories {
  507. for tag, address := range tagMap {
  508. if err := srv.runtime.repositories.Set(imageName, tag, address, true); err != nil {
  509. job.Error(err)
  510. return engine.StatusErr
  511. }
  512. }
  513. }
  514. } else if !os.IsNotExist(err) {
  515. job.Error(err)
  516. return engine.StatusErr
  517. }
  518. return engine.StatusOK
  519. }
  520. func (srv *Server) recursiveLoad(address, tmpImageDir string) error {
  521. if _, err := srv.ImageInspect(address); err != nil {
  522. utils.Debugf("Loading %s", address)
  523. imageJson, err := ioutil.ReadFile(path.Join(tmpImageDir, "repo", address, "json"))
  524. if err != nil {
  525. utils.Debugf("Error reading json", err)
  526. return err
  527. }
  528. layer, err := os.Open(path.Join(tmpImageDir, "repo", address, "layer.tar"))
  529. if err != nil {
  530. utils.Debugf("Error reading embedded tar", err)
  531. return err
  532. }
  533. img, err := NewImgJSON(imageJson)
  534. if err != nil {
  535. utils.Debugf("Error unmarshalling json", err)
  536. return err
  537. }
  538. if img.Parent != "" {
  539. if !srv.runtime.graph.Exists(img.Parent) {
  540. if err := srv.recursiveLoad(img.Parent, tmpImageDir); err != nil {
  541. return err
  542. }
  543. }
  544. }
  545. if err := srv.runtime.graph.Register(imageJson, layer, img); err != nil {
  546. return err
  547. }
  548. }
  549. utils.Debugf("Completed processing %s", address)
  550. return nil
  551. }
  552. func (srv *Server) ImagesSearch(job *engine.Job) engine.Status {
  553. if n := len(job.Args); n != 1 {
  554. job.Errorf("Usage: %s TERM", job.Name)
  555. return engine.StatusErr
  556. }
  557. var (
  558. term = job.Args[0]
  559. metaHeaders = map[string][]string{}
  560. authConfig = &auth.AuthConfig{}
  561. )
  562. job.GetenvJson("authConfig", authConfig)
  563. job.GetenvJson("metaHeaders", metaHeaders)
  564. r, err := registry.NewRegistry(authConfig, srv.HTTPRequestFactory(metaHeaders), auth.IndexServerAddress())
  565. if err != nil {
  566. job.Error(err)
  567. return engine.StatusErr
  568. }
  569. results, err := r.SearchRepositories(term)
  570. if err != nil {
  571. job.Error(err)
  572. return engine.StatusErr
  573. }
  574. outs := engine.NewTable("star_count", 0)
  575. for _, result := range results.Results {
  576. out := &engine.Env{}
  577. out.Import(result)
  578. outs.Add(out)
  579. }
  580. outs.ReverseSort()
  581. if _, err := outs.WriteListTo(job.Stdout); err != nil {
  582. job.Error(err)
  583. return engine.StatusErr
  584. }
  585. return engine.StatusOK
  586. }
  587. func (srv *Server) ImageInsert(job *engine.Job) engine.Status {
  588. if len(job.Args) != 3 {
  589. job.Errorf("Usage: %s IMAGE URL PATH\n", job.Name)
  590. return engine.StatusErr
  591. }
  592. var (
  593. name = job.Args[0]
  594. url = job.Args[1]
  595. path = job.Args[2]
  596. )
  597. sf := utils.NewStreamFormatter(job.GetenvBool("json"))
  598. out := utils.NewWriteFlusher(job.Stdout)
  599. img, err := srv.runtime.repositories.LookupImage(name)
  600. if err != nil {
  601. job.Error(err)
  602. return engine.StatusErr
  603. }
  604. file, err := utils.Download(url)
  605. if err != nil {
  606. job.Error(err)
  607. return engine.StatusErr
  608. }
  609. defer file.Body.Close()
  610. config, _, _, err := ParseRun([]string{img.ID, "echo", "insert", url, path}, srv.runtime.sysInfo)
  611. if err != nil {
  612. job.Error(err)
  613. return engine.StatusErr
  614. }
  615. c, _, err := srv.runtime.Create(config, "")
  616. if err != nil {
  617. job.Error(err)
  618. return engine.StatusErr
  619. }
  620. if err := c.Inject(utils.ProgressReader(file.Body, int(file.ContentLength), out, sf, false, utils.TruncateID(img.ID), "Downloading"), path); err != nil {
  621. job.Error(err)
  622. return engine.StatusErr
  623. }
  624. // FIXME: Handle custom repo, tag comment, author
  625. img, err = srv.runtime.Commit(c, "", "", img.Comment, img.Author, nil)
  626. if err != nil {
  627. out.Write(sf.FormatError(err))
  628. return engine.StatusErr
  629. }
  630. out.Write(sf.FormatStatus("", img.ID))
  631. return engine.StatusOK
  632. }
  633. func (srv *Server) ImagesViz(job *engine.Job) engine.Status {
  634. images, _ := srv.runtime.graph.Map()
  635. if images == nil {
  636. return engine.StatusOK
  637. }
  638. job.Stdout.Write([]byte("digraph docker {\n"))
  639. var (
  640. parentImage *Image
  641. err error
  642. )
  643. for _, image := range images {
  644. parentImage, err = image.GetParent()
  645. if err != nil {
  646. job.Errorf("Error while getting parent image: %v", err)
  647. return engine.StatusErr
  648. }
  649. if parentImage != nil {
  650. job.Stdout.Write([]byte(" \"" + parentImage.ID + "\" -> \"" + image.ID + "\"\n"))
  651. } else {
  652. job.Stdout.Write([]byte(" base -> \"" + image.ID + "\" [style=invis]\n"))
  653. }
  654. }
  655. reporefs := make(map[string][]string)
  656. for name, repository := range srv.runtime.repositories.Repositories {
  657. for tag, id := range repository {
  658. reporefs[utils.TruncateID(id)] = append(reporefs[utils.TruncateID(id)], fmt.Sprintf("%s:%s", name, tag))
  659. }
  660. }
  661. for id, repos := range reporefs {
  662. job.Stdout.Write([]byte(" \"" + id + "\" [label=\"" + id + "\\n" + strings.Join(repos, "\\n") + "\",shape=box,fillcolor=\"paleturquoise\",style=\"filled,rounded\"];\n"))
  663. }
  664. job.Stdout.Write([]byte(" base [style=invisible]\n}\n"))
  665. return engine.StatusOK
  666. }
  667. func (srv *Server) Images(job *engine.Job) engine.Status {
  668. var (
  669. allImages map[string]*Image
  670. err error
  671. )
  672. if job.GetenvBool("all") {
  673. allImages, err = srv.runtime.graph.Map()
  674. } else {
  675. allImages, err = srv.runtime.graph.Heads()
  676. }
  677. if err != nil {
  678. job.Error(err)
  679. return engine.StatusErr
  680. }
  681. lookup := make(map[string]*engine.Env)
  682. for name, repository := range srv.runtime.repositories.Repositories {
  683. if job.Getenv("filter") != "" {
  684. if match, _ := path.Match(job.Getenv("filter"), name); !match {
  685. continue
  686. }
  687. }
  688. for tag, id := range repository {
  689. image, err := srv.runtime.graph.Get(id)
  690. if err != nil {
  691. log.Printf("Warning: couldn't load %s from %s/%s: %s", id, name, tag, err)
  692. continue
  693. }
  694. if out, exists := lookup[id]; exists {
  695. out.SetList("RepoTags", append(out.GetList("RepoTags"), fmt.Sprintf("%s:%s", name, tag)))
  696. } else {
  697. out := &engine.Env{}
  698. delete(allImages, id)
  699. out.Set("ParentId", image.Parent)
  700. out.SetList("RepoTags", []string{fmt.Sprintf("%s:%s", name, tag)})
  701. out.Set("ID", image.ID)
  702. out.SetInt64("Created", image.Created.Unix())
  703. out.SetInt64("Size", image.Size)
  704. out.SetInt64("VirtualSize", image.getParentsSize(0)+image.Size)
  705. lookup[id] = out
  706. }
  707. }
  708. }
  709. outs := engine.NewTable("Created", len(lookup))
  710. for _, value := range lookup {
  711. outs.Add(value)
  712. }
  713. // Display images which aren't part of a repository/tag
  714. if job.Getenv("filter") == "" {
  715. for _, image := range allImages {
  716. out := &engine.Env{}
  717. out.Set("ParentId", image.Parent)
  718. out.SetList("RepoTags", []string{"<none>:<none>"})
  719. out.Set("ID", image.ID)
  720. out.SetInt64("Created", image.Created.Unix())
  721. out.SetInt64("Size", image.Size)
  722. out.SetInt64("VirtualSize", image.getParentsSize(0)+image.Size)
  723. outs.Add(out)
  724. }
  725. }
  726. outs.ReverseSort()
  727. if _, err := outs.WriteListTo(job.Stdout); err != nil {
  728. job.Error(err)
  729. return engine.StatusErr
  730. }
  731. return engine.StatusOK
  732. }
  733. func (srv *Server) DockerInfo(job *engine.Job) engine.Status {
  734. images, _ := srv.runtime.graph.Map()
  735. var imgcount int
  736. if images == nil {
  737. imgcount = 0
  738. } else {
  739. imgcount = len(images)
  740. }
  741. kernelVersion := "<unknown>"
  742. if kv, err := utils.GetKernelVersion(); err == nil {
  743. kernelVersion = kv.String()
  744. }
  745. // if we still have the original dockerinit binary from before we copied it locally, let's return the path to that, since that's more intuitive (the copied path is trivial to derive by hand given VERSION)
  746. initPath := utils.DockerInitPath("")
  747. if initPath == "" {
  748. // if that fails, we'll just return the path from the runtime
  749. initPath = srv.runtime.sysInitPath
  750. }
  751. v := &engine.Env{}
  752. v.SetInt("Containers", len(srv.runtime.List()))
  753. v.SetInt("Images", imgcount)
  754. v.Set("Driver", srv.runtime.driver.String())
  755. v.SetJson("DriverStatus", srv.runtime.driver.Status())
  756. v.SetBool("MemoryLimit", srv.runtime.sysInfo.MemoryLimit)
  757. v.SetBool("SwapLimit", srv.runtime.sysInfo.SwapLimit)
  758. v.SetBool("IPv4Forwarding", !srv.runtime.sysInfo.IPv4ForwardingDisabled)
  759. v.SetBool("Debug", os.Getenv("DEBUG") != "")
  760. v.SetInt("NFd", utils.GetTotalUsedFds())
  761. v.SetInt("NGoroutines", runtime.NumGoroutine())
  762. v.Set("ExecutionDriver", srv.runtime.execDriver.Name())
  763. v.SetInt("NEventsListener", len(srv.events))
  764. v.Set("KernelVersion", kernelVersion)
  765. v.Set("IndexServerAddress", auth.IndexServerAddress())
  766. v.Set("InitSha1", utils.INITSHA1)
  767. v.Set("InitPath", initPath)
  768. if _, err := v.WriteTo(job.Stdout); err != nil {
  769. job.Error(err)
  770. return engine.StatusErr
  771. }
  772. return engine.StatusOK
  773. }
  774. func (srv *Server) ImageHistory(job *engine.Job) engine.Status {
  775. if n := len(job.Args); n != 1 {
  776. job.Errorf("Usage: %s IMAGE", job.Name)
  777. return engine.StatusErr
  778. }
  779. name := job.Args[0]
  780. image, err := srv.runtime.repositories.LookupImage(name)
  781. if err != nil {
  782. job.Error(err)
  783. return engine.StatusErr
  784. }
  785. lookupMap := make(map[string][]string)
  786. for name, repository := range srv.runtime.repositories.Repositories {
  787. for tag, id := range repository {
  788. // If the ID already has a reverse lookup, do not update it unless for "latest"
  789. if _, exists := lookupMap[id]; !exists {
  790. lookupMap[id] = []string{}
  791. }
  792. lookupMap[id] = append(lookupMap[id], name+":"+tag)
  793. }
  794. }
  795. outs := engine.NewTable("Created", 0)
  796. err = image.WalkHistory(func(img *Image) error {
  797. out := &engine.Env{}
  798. out.Set("ID", img.ID)
  799. out.SetInt64("Created", img.Created.Unix())
  800. out.Set("CreatedBy", strings.Join(img.ContainerConfig.Cmd, " "))
  801. out.SetList("Tags", lookupMap[img.ID])
  802. out.SetInt64("Size", img.Size)
  803. outs.Add(out)
  804. return nil
  805. })
  806. outs.ReverseSort()
  807. if _, err := outs.WriteListTo(job.Stdout); err != nil {
  808. job.Error(err)
  809. return engine.StatusErr
  810. }
  811. return engine.StatusOK
  812. }
  813. func (srv *Server) ContainerTop(job *engine.Job) engine.Status {
  814. if len(job.Args) != 1 && len(job.Args) != 2 {
  815. job.Errorf("Not enough arguments. Usage: %s CONTAINER [PS_ARGS]\n", job.Name)
  816. return engine.StatusErr
  817. }
  818. var (
  819. name = job.Args[0]
  820. psArgs = "-ef"
  821. )
  822. if len(job.Args) == 2 && job.Args[1] != "" {
  823. psArgs = job.Args[1]
  824. }
  825. if container := srv.runtime.Get(name); container != nil {
  826. if !container.State.IsRunning() {
  827. job.Errorf("Container %s is not running", name)
  828. return engine.StatusErr
  829. }
  830. pids, err := cgroups.GetPidsForContainer(container.ID)
  831. if err != nil {
  832. job.Error(err)
  833. return engine.StatusErr
  834. }
  835. output, err := exec.Command("ps", psArgs).Output()
  836. if err != nil {
  837. job.Errorf("Error running ps: %s", err)
  838. return engine.StatusErr
  839. }
  840. lines := strings.Split(string(output), "\n")
  841. header := strings.Fields(lines[0])
  842. out := &engine.Env{}
  843. out.SetList("Titles", header)
  844. pidIndex := -1
  845. for i, name := range header {
  846. if name == "PID" {
  847. pidIndex = i
  848. }
  849. }
  850. if pidIndex == -1 {
  851. job.Errorf("Couldn't find PID field in ps output")
  852. return engine.StatusErr
  853. }
  854. processes := [][]string{}
  855. for _, line := range lines[1:] {
  856. if len(line) == 0 {
  857. continue
  858. }
  859. fields := strings.Fields(line)
  860. p, err := strconv.Atoi(fields[pidIndex])
  861. if err != nil {
  862. job.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err)
  863. return engine.StatusErr
  864. }
  865. for _, pid := range pids {
  866. if pid == p {
  867. // Make sure number of fields equals number of header titles
  868. // merging "overhanging" fields
  869. process := fields[:len(header)-1]
  870. process = append(process, strings.Join(fields[len(header)-1:], " "))
  871. processes = append(processes, process)
  872. }
  873. }
  874. }
  875. out.SetJson("Processes", processes)
  876. out.WriteTo(job.Stdout)
  877. return engine.StatusOK
  878. }
  879. job.Errorf("No such container: %s", name)
  880. return engine.StatusErr
  881. }
  882. func (srv *Server) ContainerChanges(job *engine.Job) engine.Status {
  883. if n := len(job.Args); n != 1 {
  884. job.Errorf("Usage: %s CONTAINER", job.Name)
  885. return engine.StatusErr
  886. }
  887. name := job.Args[0]
  888. if container := srv.runtime.Get(name); container != nil {
  889. outs := engine.NewTable("", 0)
  890. changes, err := container.Changes()
  891. if err != nil {
  892. job.Error(err)
  893. return engine.StatusErr
  894. }
  895. for _, change := range changes {
  896. out := &engine.Env{}
  897. if err := out.Import(change); err != nil {
  898. job.Error(err)
  899. return engine.StatusErr
  900. }
  901. outs.Add(out)
  902. }
  903. if _, err := outs.WriteListTo(job.Stdout); err != nil {
  904. job.Error(err)
  905. return engine.StatusErr
  906. }
  907. } else {
  908. job.Errorf("No such container: %s", name)
  909. return engine.StatusErr
  910. }
  911. return engine.StatusOK
  912. }
  913. func (srv *Server) Containers(all, size bool, n int, since, before string) []APIContainers {
  914. var foundBefore bool
  915. var displayed int
  916. out := []APIContainers{}
  917. names := map[string][]string{}
  918. srv.runtime.containerGraph.Walk("/", func(p string, e *graphdb.Entity) error {
  919. names[e.ID()] = append(names[e.ID()], p)
  920. return nil
  921. }, -1)
  922. for _, container := range srv.runtime.List() {
  923. if !container.State.IsRunning() && !all && n == -1 && since == "" && before == "" {
  924. continue
  925. }
  926. if before != "" && !foundBefore {
  927. if container.ID == before || utils.TruncateID(container.ID) == before {
  928. foundBefore = true
  929. }
  930. continue
  931. }
  932. if displayed == n {
  933. break
  934. }
  935. if container.ID == since || utils.TruncateID(container.ID) == since {
  936. break
  937. }
  938. displayed++
  939. c := createAPIContainer(names[container.ID], container, size, srv.runtime)
  940. out = append(out, c)
  941. }
  942. return out
  943. }
  944. func createAPIContainer(names []string, container *Container, size bool, runtime *Runtime) APIContainers {
  945. c := APIContainers{
  946. ID: container.ID,
  947. }
  948. c.Names = names
  949. c.Image = runtime.repositories.ImageName(container.Image)
  950. c.Command = fmt.Sprintf("%s %s", container.Path, strings.Join(container.Args, " "))
  951. c.Created = container.Created.Unix()
  952. c.Status = container.State.String()
  953. c.Ports = container.NetworkSettings.PortMappingAPI()
  954. if size {
  955. c.SizeRw, c.SizeRootFs = container.GetSize()
  956. }
  957. return c
  958. }
  959. func (srv *Server) ContainerCommit(job *engine.Job) engine.Status {
  960. if len(job.Args) != 1 {
  961. job.Errorf("Not enough arguments. Usage: %s CONTAINER\n", job.Name)
  962. return engine.StatusErr
  963. }
  964. name := job.Args[0]
  965. container := srv.runtime.Get(name)
  966. if container == nil {
  967. job.Errorf("No such container: %s", name)
  968. return engine.StatusErr
  969. }
  970. var config Config
  971. if err := job.GetenvJson("config", &config); err != nil {
  972. job.Error(err)
  973. return engine.StatusErr
  974. }
  975. img, err := srv.runtime.Commit(container, job.Getenv("repo"), job.Getenv("tag"), job.Getenv("comment"), job.Getenv("author"), &config)
  976. if err != nil {
  977. job.Error(err)
  978. return engine.StatusErr
  979. }
  980. job.Printf("%s\n", img.ID)
  981. return engine.StatusOK
  982. }
  983. func (srv *Server) ImageTag(job *engine.Job) engine.Status {
  984. if len(job.Args) != 2 && len(job.Args) != 3 {
  985. job.Errorf("Usage: %s IMAGE REPOSITORY [TAG]\n", job.Name)
  986. return engine.StatusErr
  987. }
  988. var tag string
  989. if len(job.Args) == 3 {
  990. tag = job.Args[2]
  991. }
  992. if err := srv.runtime.repositories.Set(job.Args[1], tag, job.Args[0], job.GetenvBool("force")); err != nil {
  993. job.Error(err)
  994. return engine.StatusErr
  995. }
  996. return engine.StatusOK
  997. }
  998. func (srv *Server) pullImage(r *registry.Registry, out io.Writer, imgID, endpoint string, token []string, sf *utils.StreamFormatter) error {
  999. history, err := r.GetRemoteHistory(imgID, endpoint, token)
  1000. if err != nil {
  1001. return err
  1002. }
  1003. out.Write(sf.FormatProgress(utils.TruncateID(imgID), "Pulling dependent layers", nil))
  1004. // FIXME: Try to stream the images?
  1005. // FIXME: Launch the getRemoteImage() in goroutines
  1006. for i := len(history) - 1; i >= 0; i-- {
  1007. id := history[i]
  1008. // ensure no two downloads of the same layer happen at the same time
  1009. if c, err := srv.poolAdd("pull", "layer:"+id); err != nil {
  1010. utils.Errorf("Image (id: %s) pull is already running, skipping: %v", id, err)
  1011. <-c
  1012. }
  1013. defer srv.poolRemove("pull", "layer:"+id)
  1014. if !srv.runtime.graph.Exists(id) {
  1015. out.Write(sf.FormatProgress(utils.TruncateID(id), "Pulling metadata", nil))
  1016. imgJSON, imgSize, err := r.GetRemoteImageJSON(id, endpoint, token)
  1017. if err != nil {
  1018. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
  1019. // FIXME: Keep going in case of error?
  1020. return err
  1021. }
  1022. img, err := NewImgJSON(imgJSON)
  1023. if err != nil {
  1024. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
  1025. return fmt.Errorf("Failed to parse json: %s", err)
  1026. }
  1027. // Get the layer
  1028. out.Write(sf.FormatProgress(utils.TruncateID(id), "Pulling fs layer", nil))
  1029. layer, err := r.GetRemoteImageLayer(img.ID, endpoint, token)
  1030. if err != nil {
  1031. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
  1032. return err
  1033. }
  1034. defer layer.Close()
  1035. if err := srv.runtime.graph.Register(imgJSON, utils.ProgressReader(layer, imgSize, out, sf, false, utils.TruncateID(id), "Downloading"), img); err != nil {
  1036. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error downloading dependent layers", nil))
  1037. return err
  1038. }
  1039. }
  1040. out.Write(sf.FormatProgress(utils.TruncateID(id), "Download complete", nil))
  1041. }
  1042. return nil
  1043. }
  1044. func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, localName, remoteName, askedTag string, sf *utils.StreamFormatter, parallel bool) error {
  1045. out.Write(sf.FormatStatus("", "Pulling repository %s", localName))
  1046. repoData, err := r.GetRepositoryData(remoteName)
  1047. if err != nil {
  1048. return err
  1049. }
  1050. utils.Debugf("Retrieving the tag list")
  1051. tagsList, err := r.GetRemoteTags(repoData.Endpoints, remoteName, repoData.Tokens)
  1052. if err != nil {
  1053. utils.Errorf("%v", err)
  1054. return err
  1055. }
  1056. for tag, id := range tagsList {
  1057. repoData.ImgList[id] = &registry.ImgData{
  1058. ID: id,
  1059. Tag: tag,
  1060. Checksum: "",
  1061. }
  1062. }
  1063. utils.Debugf("Registering tags")
  1064. // If no tag has been specified, pull them all
  1065. if askedTag == "" {
  1066. for tag, id := range tagsList {
  1067. repoData.ImgList[id].Tag = tag
  1068. }
  1069. } else {
  1070. // Otherwise, check that the tag exists and use only that one
  1071. id, exists := tagsList[askedTag]
  1072. if !exists {
  1073. return fmt.Errorf("Tag %s not found in repository %s", askedTag, localName)
  1074. }
  1075. repoData.ImgList[id].Tag = askedTag
  1076. }
  1077. errors := make(chan error)
  1078. for _, image := range repoData.ImgList {
  1079. downloadImage := func(img *registry.ImgData) {
  1080. if askedTag != "" && img.Tag != askedTag {
  1081. utils.Debugf("(%s) does not match %s (id: %s), skipping", img.Tag, askedTag, img.ID)
  1082. if parallel {
  1083. errors <- nil
  1084. }
  1085. return
  1086. }
  1087. if img.Tag == "" {
  1088. utils.Debugf("Image (id: %s) present in this repository but untagged, skipping", img.ID)
  1089. if parallel {
  1090. errors <- nil
  1091. }
  1092. return
  1093. }
  1094. // ensure no two downloads of the same image happen at the same time
  1095. if c, err := srv.poolAdd("pull", "img:"+img.ID); err != nil {
  1096. if c != nil {
  1097. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Layer already being pulled by another client. Waiting.", nil))
  1098. <-c
  1099. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Download complete", nil))
  1100. } else {
  1101. utils.Errorf("Image (id: %s) pull is already running, skipping: %v", img.ID, err)
  1102. }
  1103. if parallel {
  1104. errors <- nil
  1105. }
  1106. return
  1107. }
  1108. defer srv.poolRemove("pull", "img:"+img.ID)
  1109. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s", img.Tag, localName), nil))
  1110. success := false
  1111. var lastErr error
  1112. for _, ep := range repoData.Endpoints {
  1113. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s, endpoint: %s", img.Tag, localName, ep), nil))
  1114. if err := srv.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil {
  1115. // Its not ideal that only the last error is returned, it would be better to concatenate the errors.
  1116. // As the error is also given to the output stream the user will see the error.
  1117. lastErr = err
  1118. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Error pulling image (%s) from %s, endpoint: %s, %s", img.Tag, localName, ep, err), nil))
  1119. continue
  1120. }
  1121. success = true
  1122. break
  1123. }
  1124. if !success {
  1125. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Error pulling image (%s) from %s, %s", img.Tag, localName, lastErr), nil))
  1126. if parallel {
  1127. errors <- fmt.Errorf("Could not find repository on any of the indexed registries.")
  1128. return
  1129. }
  1130. }
  1131. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Download complete", nil))
  1132. if parallel {
  1133. errors <- nil
  1134. }
  1135. }
  1136. if parallel {
  1137. go downloadImage(image)
  1138. } else {
  1139. downloadImage(image)
  1140. }
  1141. }
  1142. if parallel {
  1143. var lastError error
  1144. for i := 0; i < len(repoData.ImgList); i++ {
  1145. if err := <-errors; err != nil {
  1146. lastError = err
  1147. }
  1148. }
  1149. if lastError != nil {
  1150. return lastError
  1151. }
  1152. }
  1153. for tag, id := range tagsList {
  1154. if askedTag != "" && tag != askedTag {
  1155. continue
  1156. }
  1157. if err := srv.runtime.repositories.Set(localName, tag, id, true); err != nil {
  1158. return err
  1159. }
  1160. }
  1161. if err := srv.runtime.repositories.Save(); err != nil {
  1162. return err
  1163. }
  1164. return nil
  1165. }
  1166. func (srv *Server) poolAdd(kind, key string) (chan struct{}, error) {
  1167. srv.Lock()
  1168. defer srv.Unlock()
  1169. if c, exists := srv.pullingPool[key]; exists {
  1170. return c, fmt.Errorf("pull %s is already in progress", key)
  1171. }
  1172. if c, exists := srv.pushingPool[key]; exists {
  1173. return c, fmt.Errorf("push %s is already in progress", key)
  1174. }
  1175. c := make(chan struct{})
  1176. switch kind {
  1177. case "pull":
  1178. srv.pullingPool[key] = c
  1179. case "push":
  1180. srv.pushingPool[key] = c
  1181. default:
  1182. return nil, fmt.Errorf("Unknown pool type")
  1183. }
  1184. return c, nil
  1185. }
  1186. func (srv *Server) poolRemove(kind, key string) error {
  1187. srv.Lock()
  1188. defer srv.Unlock()
  1189. switch kind {
  1190. case "pull":
  1191. if c, exists := srv.pullingPool[key]; exists {
  1192. close(c)
  1193. delete(srv.pullingPool, key)
  1194. }
  1195. case "push":
  1196. if c, exists := srv.pushingPool[key]; exists {
  1197. close(c)
  1198. delete(srv.pushingPool, key)
  1199. }
  1200. default:
  1201. return fmt.Errorf("Unknown pool type")
  1202. }
  1203. return nil
  1204. }
  1205. func (srv *Server) ImagePull(job *engine.Job) engine.Status {
  1206. if n := len(job.Args); n != 1 && n != 2 {
  1207. job.Errorf("Usage: %s IMAGE [TAG]", job.Name)
  1208. return engine.StatusErr
  1209. }
  1210. var (
  1211. localName = job.Args[0]
  1212. tag string
  1213. sf = utils.NewStreamFormatter(job.GetenvBool("json"))
  1214. out = utils.NewWriteFlusher(job.Stdout)
  1215. authConfig *auth.AuthConfig
  1216. metaHeaders map[string][]string
  1217. )
  1218. if len(job.Args) > 1 {
  1219. tag = job.Args[1]
  1220. }
  1221. job.GetenvJson("authConfig", authConfig)
  1222. job.GetenvJson("metaHeaders", metaHeaders)
  1223. c, err := srv.poolAdd("pull", localName+":"+tag)
  1224. if err != nil {
  1225. if c != nil {
  1226. // Another pull of the same repository is already taking place; just wait for it to finish
  1227. out.Write(sf.FormatStatus("", "Repository %s already being pulled by another client. Waiting.", localName))
  1228. <-c
  1229. return engine.StatusOK
  1230. }
  1231. job.Error(err)
  1232. return engine.StatusErr
  1233. }
  1234. defer srv.poolRemove("pull", localName+":"+tag)
  1235. // Resolve the Repository name from fqn to endpoint + name
  1236. endpoint, remoteName, err := registry.ResolveRepositoryName(localName)
  1237. if err != nil {
  1238. job.Error(err)
  1239. return engine.StatusErr
  1240. }
  1241. r, err := registry.NewRegistry(authConfig, srv.HTTPRequestFactory(metaHeaders), endpoint)
  1242. if err != nil {
  1243. job.Error(err)
  1244. return engine.StatusErr
  1245. }
  1246. if endpoint == auth.IndexServerAddress() {
  1247. // If pull "index.docker.io/foo/bar", it's stored locally under "foo/bar"
  1248. localName = remoteName
  1249. }
  1250. if err = srv.pullRepository(r, out, localName, remoteName, tag, sf, job.GetenvBool("parallel")); err != nil {
  1251. job.Error(err)
  1252. return engine.StatusErr
  1253. }
  1254. return engine.StatusOK
  1255. }
  1256. // Retrieve the all the images to be uploaded in the correct order
  1257. func (srv *Server) getImageList(localRepo map[string]string) ([]string, map[string][]string, error) {
  1258. var (
  1259. imageList []string
  1260. imagesSeen map[string]bool = make(map[string]bool)
  1261. tagsByImage map[string][]string = make(map[string][]string)
  1262. )
  1263. for tag, id := range localRepo {
  1264. var imageListForThisTag []string
  1265. tagsByImage[id] = append(tagsByImage[id], tag)
  1266. for img, err := srv.runtime.graph.Get(id); img != nil; img, err = img.GetParent() {
  1267. if err != nil {
  1268. return nil, nil, err
  1269. }
  1270. if imagesSeen[img.ID] {
  1271. // This image is already on the list, we can ignore it and all its parents
  1272. break
  1273. }
  1274. imagesSeen[img.ID] = true
  1275. imageListForThisTag = append(imageListForThisTag, img.ID)
  1276. }
  1277. // reverse the image list for this tag (so the "most"-parent image is first)
  1278. for i, j := 0, len(imageListForThisTag)-1; i < j; i, j = i+1, j-1 {
  1279. imageListForThisTag[i], imageListForThisTag[j] = imageListForThisTag[j], imageListForThisTag[i]
  1280. }
  1281. // append to main image list
  1282. imageList = append(imageList, imageListForThisTag...)
  1283. }
  1284. utils.Debugf("Image list: %v", imageList)
  1285. utils.Debugf("Tags by image: %v", tagsByImage)
  1286. return imageList, tagsByImage, nil
  1287. }
  1288. func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, localName, remoteName string, localRepo map[string]string, sf *utils.StreamFormatter) error {
  1289. out = utils.NewWriteFlusher(out)
  1290. utils.Debugf("Local repo: %s", localRepo)
  1291. imgList, tagsByImage, err := srv.getImageList(localRepo)
  1292. if err != nil {
  1293. return err
  1294. }
  1295. out.Write(sf.FormatStatus("", "Sending image list"))
  1296. var repoData *registry.RepositoryData
  1297. var imageIndex []*registry.ImgData
  1298. for _, imgId := range imgList {
  1299. if tags, exists := tagsByImage[imgId]; exists {
  1300. // If an image has tags you must add an entry in the image index
  1301. // for each tag
  1302. for _, tag := range tags {
  1303. imageIndex = append(imageIndex, &registry.ImgData{
  1304. ID: imgId,
  1305. Tag: tag,
  1306. })
  1307. }
  1308. } else {
  1309. // If the image does not have a tag it still needs to be sent to the
  1310. // registry with an empty tag so that it is accociated with the repository
  1311. imageIndex = append(imageIndex, &registry.ImgData{
  1312. ID: imgId,
  1313. Tag: "",
  1314. })
  1315. }
  1316. }
  1317. utils.Debugf("Preparing to push %s with the following images and tags\n", localRepo)
  1318. for _, data := range imageIndex {
  1319. utils.Debugf("Pushing ID: %s with Tag: %s\n", data.ID, data.Tag)
  1320. }
  1321. // Register all the images in a repository with the registry
  1322. // If an image is not in this list it will not be associated with the repository
  1323. repoData, err = r.PushImageJSONIndex(remoteName, imageIndex, false, nil)
  1324. if err != nil {
  1325. return err
  1326. }
  1327. for _, ep := range repoData.Endpoints {
  1328. out.Write(sf.FormatStatus("", "Pushing repository %s (%d tags)", localName, len(localRepo)))
  1329. for _, imgId := range imgList {
  1330. if r.LookupRemoteImage(imgId, ep, repoData.Tokens) {
  1331. out.Write(sf.FormatStatus("", "Image %s already pushed, skipping", utils.TruncateID(imgId)))
  1332. } else {
  1333. if _, err := srv.pushImage(r, out, remoteName, imgId, ep, repoData.Tokens, sf); err != nil {
  1334. // FIXME: Continue on error?
  1335. return err
  1336. }
  1337. }
  1338. for _, tag := range tagsByImage[imgId] {
  1339. out.Write(sf.FormatStatus("", "Pushing tag for rev [%s] on {%s}", utils.TruncateID(imgId), ep+"repositories/"+remoteName+"/tags/"+tag))
  1340. if err := r.PushRegistryTag(remoteName, imgId, tag, ep, repoData.Tokens); err != nil {
  1341. return err
  1342. }
  1343. }
  1344. }
  1345. }
  1346. if _, err := r.PushImageJSONIndex(remoteName, imageIndex, true, repoData.Endpoints); err != nil {
  1347. return err
  1348. }
  1349. return nil
  1350. }
  1351. func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgID, ep string, token []string, sf *utils.StreamFormatter) (checksum string, err error) {
  1352. out = utils.NewWriteFlusher(out)
  1353. jsonRaw, err := ioutil.ReadFile(path.Join(srv.runtime.graph.Root, imgID, "json"))
  1354. if err != nil {
  1355. return "", fmt.Errorf("Cannot retrieve the path for {%s}: %s", imgID, err)
  1356. }
  1357. out.Write(sf.FormatProgress(utils.TruncateID(imgID), "Pushing", nil))
  1358. imgData := &registry.ImgData{
  1359. ID: imgID,
  1360. }
  1361. // Send the json
  1362. if err := r.PushImageJSONRegistry(imgData, jsonRaw, ep, token); err != nil {
  1363. if err == registry.ErrAlreadyExists {
  1364. out.Write(sf.FormatProgress(utils.TruncateID(imgData.ID), "Image already pushed, skipping", nil))
  1365. return "", nil
  1366. }
  1367. return "", err
  1368. }
  1369. layerData, err := srv.runtime.graph.TempLayerArchive(imgID, archive.Uncompressed, sf, out)
  1370. if err != nil {
  1371. return "", fmt.Errorf("Failed to generate layer archive: %s", err)
  1372. }
  1373. defer os.RemoveAll(layerData.Name())
  1374. // Send the layer
  1375. checksum, err = r.PushImageLayerRegistry(imgData.ID, utils.ProgressReader(layerData, int(layerData.Size), out, sf, false, utils.TruncateID(imgData.ID), "Pushing"), ep, token, jsonRaw)
  1376. if err != nil {
  1377. return "", err
  1378. }
  1379. imgData.Checksum = checksum
  1380. // Send the checksum
  1381. if err := r.PushImageChecksumRegistry(imgData, ep, token); err != nil {
  1382. return "", err
  1383. }
  1384. out.Write(sf.FormatProgress(utils.TruncateID(imgData.ID), "Image successfully pushed", nil))
  1385. return imgData.Checksum, nil
  1386. }
  1387. // FIXME: Allow to interrupt current push when new push of same image is done.
  1388. func (srv *Server) ImagePush(localName string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig, metaHeaders map[string][]string) error {
  1389. if _, err := srv.poolAdd("push", localName); err != nil {
  1390. return err
  1391. }
  1392. defer srv.poolRemove("push", localName)
  1393. // Resolve the Repository name from fqn to endpoint + name
  1394. endpoint, remoteName, err := registry.ResolveRepositoryName(localName)
  1395. if err != nil {
  1396. return err
  1397. }
  1398. out = utils.NewWriteFlusher(out)
  1399. img, err := srv.runtime.graph.Get(localName)
  1400. r, err2 := registry.NewRegistry(authConfig, srv.HTTPRequestFactory(metaHeaders), endpoint)
  1401. if err2 != nil {
  1402. return err2
  1403. }
  1404. if err != nil {
  1405. reposLen := len(srv.runtime.repositories.Repositories[localName])
  1406. out.Write(sf.FormatStatus("", "The push refers to a repository [%s] (len: %d)", localName, reposLen))
  1407. // If it fails, try to get the repository
  1408. if localRepo, exists := srv.runtime.repositories.Repositories[localName]; exists {
  1409. if err := srv.pushRepository(r, out, localName, remoteName, localRepo, sf); err != nil {
  1410. return err
  1411. }
  1412. return nil
  1413. }
  1414. return err
  1415. }
  1416. var token []string
  1417. out.Write(sf.FormatStatus("", "The push refers to an image: [%s]", localName))
  1418. if _, err := srv.pushImage(r, out, remoteName, img.ID, endpoint, token, sf); err != nil {
  1419. return err
  1420. }
  1421. return nil
  1422. }
  1423. func (srv *Server) ImageImport(job *engine.Job) engine.Status {
  1424. if n := len(job.Args); n != 2 && n != 3 {
  1425. job.Errorf("Usage: %s SRC REPO [TAG]", job.Name)
  1426. return engine.StatusErr
  1427. }
  1428. var (
  1429. src = job.Args[0]
  1430. repo = job.Args[1]
  1431. tag string
  1432. sf = utils.NewStreamFormatter(job.GetenvBool("json"))
  1433. out = utils.NewWriteFlusher(job.Stdout)
  1434. archive io.Reader
  1435. resp *http.Response
  1436. )
  1437. if len(job.Args) > 2 {
  1438. tag = job.Args[2]
  1439. }
  1440. if src == "-" {
  1441. archive = job.Stdin
  1442. } else {
  1443. u, err := url.Parse(src)
  1444. if err != nil {
  1445. job.Error(err)
  1446. return engine.StatusErr
  1447. }
  1448. if u.Scheme == "" {
  1449. u.Scheme = "http"
  1450. u.Host = src
  1451. u.Path = ""
  1452. }
  1453. out.Write(sf.FormatStatus("", "Downloading from %s", u))
  1454. // Download with curl (pretty progress bar)
  1455. // If curl is not available, fallback to http.Get()
  1456. resp, err = utils.Download(u.String())
  1457. if err != nil {
  1458. job.Error(err)
  1459. return engine.StatusErr
  1460. }
  1461. archive = utils.ProgressReader(resp.Body, int(resp.ContentLength), out, sf, true, "", "Importing")
  1462. }
  1463. img, err := srv.runtime.graph.Create(archive, nil, "Imported from "+src, "", nil)
  1464. if err != nil {
  1465. job.Error(err)
  1466. return engine.StatusErr
  1467. }
  1468. // Optionally register the image at REPO/TAG
  1469. if repo != "" {
  1470. if err := srv.runtime.repositories.Set(repo, tag, img.ID, true); err != nil {
  1471. job.Error(err)
  1472. return engine.StatusErr
  1473. }
  1474. }
  1475. out.Write(sf.FormatStatus("", img.ID))
  1476. return engine.StatusOK
  1477. }
  1478. func (srv *Server) ContainerCreate(job *engine.Job) engine.Status {
  1479. var name string
  1480. if len(job.Args) == 1 {
  1481. name = job.Args[0]
  1482. } else if len(job.Args) > 1 {
  1483. job.Printf("Usage: %s", job.Name)
  1484. return engine.StatusErr
  1485. }
  1486. var config Config
  1487. if err := job.ExportEnv(&config); err != nil {
  1488. job.Error(err)
  1489. return engine.StatusErr
  1490. }
  1491. if config.Memory != 0 && config.Memory < 524288 {
  1492. job.Errorf("Minimum memory limit allowed is 512k")
  1493. return engine.StatusErr
  1494. }
  1495. if config.Memory > 0 && !srv.runtime.sysInfo.MemoryLimit {
  1496. config.Memory = 0
  1497. }
  1498. if config.Memory > 0 && !srv.runtime.sysInfo.SwapLimit {
  1499. config.MemorySwap = -1
  1500. }
  1501. container, buildWarnings, err := srv.runtime.Create(&config, name)
  1502. if err != nil {
  1503. if srv.runtime.graph.IsNotExist(err) {
  1504. _, tag := utils.ParseRepositoryTag(config.Image)
  1505. if tag == "" {
  1506. tag = DEFAULTTAG
  1507. }
  1508. job.Errorf("No such image: %s (tag: %s)", config.Image, tag)
  1509. return engine.StatusErr
  1510. }
  1511. job.Error(err)
  1512. return engine.StatusErr
  1513. }
  1514. srv.LogEvent("create", container.ID, srv.runtime.repositories.ImageName(container.Image))
  1515. // FIXME: this is necessary because runtime.Create might return a nil container
  1516. // with a non-nil error. This should not happen! Once it's fixed we
  1517. // can remove this workaround.
  1518. if container != nil {
  1519. job.Printf("%s\n", container.ID)
  1520. }
  1521. for _, warning := range buildWarnings {
  1522. job.Errorf("%s\n", warning)
  1523. }
  1524. return engine.StatusOK
  1525. }
  1526. func (srv *Server) ContainerRestart(job *engine.Job) engine.Status {
  1527. if len(job.Args) != 1 {
  1528. job.Errorf("Usage: %s CONTAINER\n", job.Name)
  1529. return engine.StatusErr
  1530. }
  1531. name := job.Args[0]
  1532. t := job.GetenvInt("t")
  1533. if t == -1 {
  1534. t = 10
  1535. }
  1536. if container := srv.runtime.Get(name); container != nil {
  1537. if err := container.Restart(int(t)); err != nil {
  1538. job.Errorf("Cannot restart container %s: %s\n", name, err)
  1539. return engine.StatusErr
  1540. }
  1541. srv.LogEvent("restart", container.ID, srv.runtime.repositories.ImageName(container.Image))
  1542. } else {
  1543. job.Errorf("No such container: %s\n", name)
  1544. return engine.StatusErr
  1545. }
  1546. return engine.StatusOK
  1547. }
  1548. func (srv *Server) ContainerDestroy(job *engine.Job) engine.Status {
  1549. if len(job.Args) != 1 {
  1550. job.Errorf("Not enough arguments. Usage: %s CONTAINER\n", job.Name)
  1551. return engine.StatusErr
  1552. }
  1553. name := job.Args[0]
  1554. removeVolume := job.GetenvBool("removeVolume")
  1555. removeLink := job.GetenvBool("removeLink")
  1556. container := srv.runtime.Get(name)
  1557. if removeLink {
  1558. if container == nil {
  1559. job.Errorf("No such link: %s", name)
  1560. return engine.StatusErr
  1561. }
  1562. name, err := getFullName(name)
  1563. if err != nil {
  1564. job.Error(err)
  1565. return engine.StatusErr
  1566. }
  1567. parent, n := path.Split(name)
  1568. if parent == "/" {
  1569. job.Errorf("Conflict, cannot remove the default name of the container")
  1570. return engine.StatusErr
  1571. }
  1572. pe := srv.runtime.containerGraph.Get(parent)
  1573. if pe == nil {
  1574. job.Errorf("Cannot get parent %s for name %s", parent, name)
  1575. return engine.StatusErr
  1576. }
  1577. parentContainer := srv.runtime.Get(pe.ID())
  1578. if parentContainer != nil && parentContainer.activeLinks != nil {
  1579. if link, exists := parentContainer.activeLinks[n]; exists {
  1580. link.Disable()
  1581. } else {
  1582. utils.Debugf("Could not find active link for %s", name)
  1583. }
  1584. }
  1585. if err := srv.runtime.containerGraph.Delete(name); err != nil {
  1586. job.Error(err)
  1587. return engine.StatusErr
  1588. }
  1589. return engine.StatusOK
  1590. }
  1591. if container != nil {
  1592. if container.State.IsRunning() {
  1593. job.Errorf("Impossible to remove a running container, please stop it first")
  1594. return engine.StatusErr
  1595. }
  1596. volumes := make(map[string]struct{})
  1597. binds := make(map[string]struct{})
  1598. for _, bind := range container.hostConfig.Binds {
  1599. splitBind := strings.Split(bind, ":")
  1600. source := splitBind[0]
  1601. binds[source] = struct{}{}
  1602. }
  1603. // Store all the deleted containers volumes
  1604. for _, volumeId := range container.Volumes {
  1605. // Skip the volumes mounted from external
  1606. if _, exists := binds[volumeId]; exists {
  1607. continue
  1608. }
  1609. volumeId = strings.TrimSuffix(volumeId, "/layer")
  1610. volumeId = filepath.Base(volumeId)
  1611. volumes[volumeId] = struct{}{}
  1612. }
  1613. if err := srv.runtime.Destroy(container); err != nil {
  1614. job.Errorf("Cannot destroy container %s: %s", name, err)
  1615. return engine.StatusErr
  1616. }
  1617. srv.LogEvent("destroy", container.ID, srv.runtime.repositories.ImageName(container.Image))
  1618. if removeVolume {
  1619. // Retrieve all volumes from all remaining containers
  1620. usedVolumes := make(map[string]*Container)
  1621. for _, container := range srv.runtime.List() {
  1622. for _, containerVolumeId := range container.Volumes {
  1623. usedVolumes[containerVolumeId] = container
  1624. }
  1625. }
  1626. for volumeId := range volumes {
  1627. // If the requested volu
  1628. if c, exists := usedVolumes[volumeId]; exists {
  1629. log.Printf("The volume %s is used by the container %s. Impossible to remove it. Skipping.\n", volumeId, c.ID)
  1630. continue
  1631. }
  1632. if err := srv.runtime.volumes.Delete(volumeId); err != nil {
  1633. job.Error(err)
  1634. return engine.StatusErr
  1635. }
  1636. }
  1637. }
  1638. } else {
  1639. job.Errorf("No such container: %s", name)
  1640. return engine.StatusErr
  1641. }
  1642. return engine.StatusOK
  1643. }
  1644. var ErrImageReferenced = errors.New("Image referenced by a repository")
  1645. func (srv *Server) deleteImageAndChildren(id string, imgs *[]APIRmi, byParents map[string][]*Image) error {
  1646. // If the image is referenced by a repo, do not delete
  1647. if len(srv.runtime.repositories.ByID()[id]) != 0 {
  1648. return ErrImageReferenced
  1649. }
  1650. // If the image is not referenced but has children, go recursive
  1651. referenced := false
  1652. for _, img := range byParents[id] {
  1653. if err := srv.deleteImageAndChildren(img.ID, imgs, byParents); err != nil {
  1654. if err != ErrImageReferenced {
  1655. return err
  1656. }
  1657. referenced = true
  1658. }
  1659. }
  1660. if referenced {
  1661. return ErrImageReferenced
  1662. }
  1663. // If the image is not referenced and has no children, remove it
  1664. byParents, err := srv.runtime.graph.ByParent()
  1665. if err != nil {
  1666. return err
  1667. }
  1668. if len(byParents[id]) == 0 && srv.canDeleteImage(id) == nil {
  1669. if err := srv.runtime.repositories.DeleteAll(id); err != nil {
  1670. return err
  1671. }
  1672. err := srv.runtime.graph.Delete(id)
  1673. if err != nil {
  1674. return err
  1675. }
  1676. *imgs = append(*imgs, APIRmi{Deleted: id})
  1677. srv.LogEvent("delete", id, "")
  1678. return nil
  1679. }
  1680. return nil
  1681. }
  1682. func (srv *Server) deleteImageParents(img *Image, imgs *[]APIRmi) error {
  1683. if img.Parent != "" {
  1684. parent, err := srv.runtime.graph.Get(img.Parent)
  1685. if err != nil {
  1686. return err
  1687. }
  1688. byParents, err := srv.runtime.graph.ByParent()
  1689. if err != nil {
  1690. return err
  1691. }
  1692. // Remove all children images
  1693. if err := srv.deleteImageAndChildren(img.Parent, imgs, byParents); err != nil {
  1694. return err
  1695. }
  1696. return srv.deleteImageParents(parent, imgs)
  1697. }
  1698. return nil
  1699. }
  1700. func (srv *Server) deleteImage(img *Image, repoName, tag string) ([]APIRmi, error) {
  1701. var (
  1702. imgs = []APIRmi{}
  1703. tags = []string{}
  1704. )
  1705. //If delete by id, see if the id belong only to one repository
  1706. if repoName == "" {
  1707. for _, repoAndTag := range srv.runtime.repositories.ByID()[img.ID] {
  1708. parsedRepo, parsedTag := utils.ParseRepositoryTag(repoAndTag)
  1709. if repoName == "" || repoName == parsedRepo {
  1710. repoName = parsedRepo
  1711. if parsedTag != "" {
  1712. tags = append(tags, parsedTag)
  1713. }
  1714. } else if repoName != parsedRepo {
  1715. // the id belongs to multiple repos, like base:latest and user:test,
  1716. // in that case return conflict
  1717. return nil, fmt.Errorf("Conflict, cannot delete image %s because it is tagged in multiple repositories", utils.TruncateID(img.ID))
  1718. }
  1719. }
  1720. } else {
  1721. tags = append(tags, tag)
  1722. }
  1723. //Untag the current image
  1724. for _, tag := range tags {
  1725. tagDeleted, err := srv.runtime.repositories.Delete(repoName, tag)
  1726. if err != nil {
  1727. return nil, err
  1728. }
  1729. if tagDeleted {
  1730. imgs = append(imgs, APIRmi{Untagged: img.ID})
  1731. srv.LogEvent("untag", img.ID, "")
  1732. }
  1733. }
  1734. if len(srv.runtime.repositories.ByID()[img.ID]) == 0 {
  1735. if err := srv.deleteImageAndChildren(img.ID, &imgs, nil); err != nil {
  1736. if err != ErrImageReferenced {
  1737. return imgs, err
  1738. }
  1739. } else if err := srv.deleteImageParents(img, &imgs); err != nil {
  1740. if err != ErrImageReferenced {
  1741. return imgs, err
  1742. }
  1743. }
  1744. }
  1745. return imgs, nil
  1746. }
  1747. func (srv *Server) ImageDelete(name string, autoPrune bool) ([]APIRmi, error) {
  1748. var (
  1749. repository, tag string
  1750. img, err = srv.runtime.repositories.LookupImage(name)
  1751. )
  1752. if err != nil {
  1753. return nil, fmt.Errorf("No such image: %s", name)
  1754. }
  1755. // FIXME: What does autoPrune mean ?
  1756. if !autoPrune {
  1757. if err := srv.runtime.graph.Delete(img.ID); err != nil {
  1758. return nil, fmt.Errorf("Cannot delete image %s: %s", name, err)
  1759. }
  1760. return nil, nil
  1761. }
  1762. if !strings.Contains(img.ID, name) {
  1763. repository, tag = utils.ParseRepositoryTag(name)
  1764. }
  1765. // If we have a repo and the image is not referenced anywhere else
  1766. // then just perform an untag and do not validate.
  1767. //
  1768. // i.e. only validate if we are performing an actual delete and not
  1769. // an untag op
  1770. if repository != "" && len(srv.runtime.repositories.ByID()[img.ID]) == 1 {
  1771. // Prevent deletion if image is used by a container
  1772. if err := srv.canDeleteImage(img.ID); err != nil {
  1773. return nil, err
  1774. }
  1775. }
  1776. return srv.deleteImage(img, repository, tag)
  1777. }
  1778. func (srv *Server) canDeleteImage(imgID string) error {
  1779. for _, container := range srv.runtime.List() {
  1780. parent, err := srv.runtime.repositories.LookupImage(container.Image)
  1781. if err != nil {
  1782. return err
  1783. }
  1784. if err := parent.WalkHistory(func(p *Image) error {
  1785. if imgID == p.ID {
  1786. return fmt.Errorf("Conflict, cannot delete %s because the container %s is using it", utils.TruncateID(imgID), utils.TruncateID(container.ID))
  1787. }
  1788. return nil
  1789. }); err != nil {
  1790. return err
  1791. }
  1792. }
  1793. return nil
  1794. }
  1795. func (srv *Server) ImageGetCached(imgID string, config *Config) (*Image, error) {
  1796. // Retrieve all images
  1797. images, err := srv.runtime.graph.Map()
  1798. if err != nil {
  1799. return nil, err
  1800. }
  1801. // Store the tree in a map of map (map[parentId][childId])
  1802. imageMap := make(map[string]map[string]struct{})
  1803. for _, img := range images {
  1804. if _, exists := imageMap[img.Parent]; !exists {
  1805. imageMap[img.Parent] = make(map[string]struct{})
  1806. }
  1807. imageMap[img.Parent][img.ID] = struct{}{}
  1808. }
  1809. // Loop on the children of the given image and check the config
  1810. var match *Image
  1811. for elem := range imageMap[imgID] {
  1812. img, err := srv.runtime.graph.Get(elem)
  1813. if err != nil {
  1814. return nil, err
  1815. }
  1816. if CompareConfig(&img.ContainerConfig, config) {
  1817. if match == nil || match.Created.Before(img.Created) {
  1818. match = img
  1819. }
  1820. }
  1821. }
  1822. return match, nil
  1823. }
  1824. func (srv *Server) RegisterLinks(container *Container, hostConfig *HostConfig) error {
  1825. runtime := srv.runtime
  1826. if hostConfig != nil && hostConfig.Links != nil {
  1827. for _, l := range hostConfig.Links {
  1828. parts, err := parseLink(l)
  1829. if err != nil {
  1830. return err
  1831. }
  1832. child, err := srv.runtime.GetByName(parts["name"])
  1833. if err != nil {
  1834. return err
  1835. }
  1836. if child == nil {
  1837. return fmt.Errorf("Could not get container for %s", parts["name"])
  1838. }
  1839. if err := runtime.RegisterLink(container, child, parts["alias"]); err != nil {
  1840. return err
  1841. }
  1842. }
  1843. // After we load all the links into the runtime
  1844. // set them to nil on the hostconfig
  1845. hostConfig.Links = nil
  1846. if err := container.writeHostConfig(); err != nil {
  1847. return err
  1848. }
  1849. }
  1850. return nil
  1851. }
  1852. func (srv *Server) ContainerStart(job *engine.Job) engine.Status {
  1853. if len(job.Args) < 1 {
  1854. job.Errorf("Usage: %s container_id", job.Name)
  1855. return engine.StatusErr
  1856. }
  1857. name := job.Args[0]
  1858. runtime := srv.runtime
  1859. container := runtime.Get(name)
  1860. if container == nil {
  1861. job.Errorf("No such container: %s", name)
  1862. return engine.StatusErr
  1863. }
  1864. // If no environment was set, then no hostconfig was passed.
  1865. if len(job.Environ()) > 0 {
  1866. var hostConfig HostConfig
  1867. if err := job.ExportEnv(&hostConfig); err != nil {
  1868. job.Error(err)
  1869. return engine.StatusErr
  1870. }
  1871. // Validate the HostConfig binds. Make sure that:
  1872. // 1) the source of a bind mount isn't /
  1873. // The bind mount "/:/foo" isn't allowed.
  1874. // 2) Check that the source exists
  1875. // The source to be bind mounted must exist.
  1876. for _, bind := range hostConfig.Binds {
  1877. splitBind := strings.Split(bind, ":")
  1878. source := splitBind[0]
  1879. // refuse to bind mount "/" to the container
  1880. if source == "/" {
  1881. job.Errorf("Invalid bind mount '%s' : source can't be '/'", bind)
  1882. return engine.StatusErr
  1883. }
  1884. // ensure the source exists on the host
  1885. _, err := os.Stat(source)
  1886. if err != nil && os.IsNotExist(err) {
  1887. err = os.MkdirAll(source, 0755)
  1888. if err != nil {
  1889. job.Errorf("Could not create local directory '%s' for bind mount: %s!", source, err.Error())
  1890. return engine.StatusErr
  1891. }
  1892. }
  1893. }
  1894. // Register any links from the host config before starting the container
  1895. if err := srv.RegisterLinks(container, &hostConfig); err != nil {
  1896. job.Error(err)
  1897. return engine.StatusErr
  1898. }
  1899. container.hostConfig = &hostConfig
  1900. container.ToDisk()
  1901. }
  1902. if err := container.Start(); err != nil {
  1903. job.Errorf("Cannot start container %s: %s", name, err)
  1904. return engine.StatusErr
  1905. }
  1906. srv.LogEvent("start", container.ID, runtime.repositories.ImageName(container.Image))
  1907. return engine.StatusOK
  1908. }
  1909. func (srv *Server) ContainerStop(job *engine.Job) engine.Status {
  1910. if len(job.Args) != 1 {
  1911. job.Errorf("Usage: %s CONTAINER\n", job.Name)
  1912. return engine.StatusErr
  1913. }
  1914. name := job.Args[0]
  1915. t := job.GetenvInt("t")
  1916. if t == -1 {
  1917. t = 10
  1918. }
  1919. if container := srv.runtime.Get(name); container != nil {
  1920. if err := container.Stop(int(t)); err != nil {
  1921. job.Errorf("Cannot stop container %s: %s\n", name, err)
  1922. return engine.StatusErr
  1923. }
  1924. srv.LogEvent("stop", container.ID, srv.runtime.repositories.ImageName(container.Image))
  1925. } else {
  1926. job.Errorf("No such container: %s\n", name)
  1927. return engine.StatusErr
  1928. }
  1929. return engine.StatusOK
  1930. }
  1931. func (srv *Server) ContainerWait(job *engine.Job) engine.Status {
  1932. if len(job.Args) != 1 {
  1933. job.Errorf("Usage: %s", job.Name)
  1934. return engine.StatusErr
  1935. }
  1936. name := job.Args[0]
  1937. if container := srv.runtime.Get(name); container != nil {
  1938. status := container.Wait()
  1939. job.Printf("%d\n", status)
  1940. return engine.StatusOK
  1941. }
  1942. job.Errorf("%s: no such container: %s", job.Name, name)
  1943. return engine.StatusErr
  1944. }
  1945. func (srv *Server) ContainerResize(job *engine.Job) engine.Status {
  1946. if len(job.Args) != 3 {
  1947. job.Errorf("Not enough arguments. Usage: %s CONTAINER HEIGHT WIDTH\n", job.Name)
  1948. return engine.StatusErr
  1949. }
  1950. name := job.Args[0]
  1951. height, err := strconv.Atoi(job.Args[1])
  1952. if err != nil {
  1953. job.Error(err)
  1954. return engine.StatusErr
  1955. }
  1956. width, err := strconv.Atoi(job.Args[2])
  1957. if err != nil {
  1958. job.Error(err)
  1959. return engine.StatusErr
  1960. }
  1961. if container := srv.runtime.Get(name); container != nil {
  1962. if err := container.Resize(height, width); err != nil {
  1963. job.Error(err)
  1964. return engine.StatusErr
  1965. }
  1966. return engine.StatusOK
  1967. }
  1968. job.Errorf("No such container: %s", name)
  1969. return engine.StatusErr
  1970. }
  1971. func (srv *Server) ContainerAttach(job *engine.Job) engine.Status {
  1972. if len(job.Args) != 1 {
  1973. job.Errorf("Usage: %s CONTAINER\n", job.Name)
  1974. return engine.StatusErr
  1975. }
  1976. var (
  1977. name = job.Args[0]
  1978. logs = job.GetenvBool("logs")
  1979. stream = job.GetenvBool("stream")
  1980. stdin = job.GetenvBool("stdin")
  1981. stdout = job.GetenvBool("stdout")
  1982. stderr = job.GetenvBool("stderr")
  1983. )
  1984. container := srv.runtime.Get(name)
  1985. if container == nil {
  1986. job.Errorf("No such container: %s", name)
  1987. return engine.StatusErr
  1988. }
  1989. //logs
  1990. if logs {
  1991. cLog, err := container.ReadLog("json")
  1992. if err != nil && os.IsNotExist(err) {
  1993. // Legacy logs
  1994. utils.Debugf("Old logs format")
  1995. if stdout {
  1996. cLog, err := container.ReadLog("stdout")
  1997. if err != nil {
  1998. utils.Errorf("Error reading logs (stdout): %s", err)
  1999. } else if _, err := io.Copy(job.Stdout, cLog); err != nil {
  2000. utils.Errorf("Error streaming logs (stdout): %s", err)
  2001. }
  2002. }
  2003. if stderr {
  2004. cLog, err := container.ReadLog("stderr")
  2005. if err != nil {
  2006. utils.Errorf("Error reading logs (stderr): %s", err)
  2007. } else if _, err := io.Copy(job.Stderr, cLog); err != nil {
  2008. utils.Errorf("Error streaming logs (stderr): %s", err)
  2009. }
  2010. }
  2011. } else if err != nil {
  2012. utils.Errorf("Error reading logs (json): %s", err)
  2013. } else {
  2014. dec := json.NewDecoder(cLog)
  2015. for {
  2016. l := &utils.JSONLog{}
  2017. if err := dec.Decode(l); err == io.EOF {
  2018. break
  2019. } else if err != nil {
  2020. utils.Errorf("Error streaming logs: %s", err)
  2021. break
  2022. }
  2023. if l.Stream == "stdout" && stdout {
  2024. fmt.Fprintf(job.Stdout, "%s", l.Log)
  2025. }
  2026. if l.Stream == "stderr" && stderr {
  2027. fmt.Fprintf(job.Stderr, "%s", l.Log)
  2028. }
  2029. }
  2030. }
  2031. }
  2032. //stream
  2033. if stream {
  2034. if container.State.IsGhost() {
  2035. job.Errorf("Impossible to attach to a ghost container")
  2036. return engine.StatusErr
  2037. }
  2038. var (
  2039. cStdin io.ReadCloser
  2040. cStdout, cStderr io.Writer
  2041. cStdinCloser io.Closer
  2042. )
  2043. if stdin {
  2044. r, w := io.Pipe()
  2045. go func() {
  2046. defer w.Close()
  2047. defer utils.Debugf("Closing buffered stdin pipe")
  2048. io.Copy(w, job.Stdin)
  2049. }()
  2050. cStdin = r
  2051. cStdinCloser = job.Stdin
  2052. }
  2053. if stdout {
  2054. cStdout = job.Stdout
  2055. }
  2056. if stderr {
  2057. cStderr = job.Stderr
  2058. }
  2059. <-container.Attach(cStdin, cStdinCloser, cStdout, cStderr)
  2060. // If we are in stdinonce mode, wait for the process to end
  2061. // otherwise, simply return
  2062. if container.Config.StdinOnce && !container.Config.Tty {
  2063. container.Wait()
  2064. }
  2065. }
  2066. return engine.StatusOK
  2067. }
  2068. func (srv *Server) ContainerInspect(name string) (*Container, error) {
  2069. if container := srv.runtime.Get(name); container != nil {
  2070. return container, nil
  2071. }
  2072. return nil, fmt.Errorf("No such container: %s", name)
  2073. }
  2074. func (srv *Server) ImageInspect(name string) (*Image, error) {
  2075. if image, err := srv.runtime.repositories.LookupImage(name); err == nil && image != nil {
  2076. return image, nil
  2077. }
  2078. return nil, fmt.Errorf("No such image: %s", name)
  2079. }
  2080. func (srv *Server) ContainerCopy(job *engine.Job) engine.Status {
  2081. if len(job.Args) != 2 {
  2082. job.Errorf("Usage: %s CONTAINER RESOURCE\n", job.Name)
  2083. return engine.StatusErr
  2084. }
  2085. var (
  2086. name = job.Args[0]
  2087. resource = job.Args[1]
  2088. )
  2089. if container := srv.runtime.Get(name); container != nil {
  2090. data, err := container.Copy(resource)
  2091. if err != nil {
  2092. job.Error(err)
  2093. return engine.StatusErr
  2094. }
  2095. if _, err := io.Copy(job.Stdout, data); err != nil {
  2096. job.Error(err)
  2097. return engine.StatusErr
  2098. }
  2099. return engine.StatusOK
  2100. }
  2101. job.Errorf("No such container: %s", name)
  2102. return engine.StatusErr
  2103. }
  2104. func NewServer(eng *engine.Engine, config *DaemonConfig) (*Server, error) {
  2105. runtime, err := NewRuntime(config)
  2106. if err != nil {
  2107. return nil, err
  2108. }
  2109. srv := &Server{
  2110. Eng: eng,
  2111. runtime: runtime,
  2112. pullingPool: make(map[string]chan struct{}),
  2113. pushingPool: make(map[string]chan struct{}),
  2114. events: make([]utils.JSONMessage, 0, 64), //only keeps the 64 last events
  2115. listeners: make(map[string]chan utils.JSONMessage),
  2116. }
  2117. runtime.srv = srv
  2118. return srv, nil
  2119. }
  2120. func (srv *Server) HTTPRequestFactory(metaHeaders map[string][]string) *utils.HTTPRequestFactory {
  2121. srv.Lock()
  2122. defer srv.Unlock()
  2123. v := dockerVersion()
  2124. httpVersion := make([]utils.VersionInfo, 0, 4)
  2125. httpVersion = append(httpVersion, &simpleVersionInfo{"docker", v.Get("Version")})
  2126. httpVersion = append(httpVersion, &simpleVersionInfo{"go", v.Get("GoVersion")})
  2127. httpVersion = append(httpVersion, &simpleVersionInfo{"git-commit", v.Get("GitCommit")})
  2128. httpVersion = append(httpVersion, &simpleVersionInfo{"kernel", v.Get("KernelVersion")})
  2129. httpVersion = append(httpVersion, &simpleVersionInfo{"os", v.Get("Os")})
  2130. httpVersion = append(httpVersion, &simpleVersionInfo{"arch", v.Get("Arch")})
  2131. ud := utils.NewHTTPUserAgentDecorator(httpVersion...)
  2132. md := &utils.HTTPMetaHeadersDecorator{
  2133. Headers: metaHeaders,
  2134. }
  2135. factory := utils.NewHTTPRequestFactory(ud, md)
  2136. return factory
  2137. }
  2138. func (srv *Server) LogEvent(action, id, from string) *utils.JSONMessage {
  2139. now := time.Now().UTC().Unix()
  2140. jm := utils.JSONMessage{Status: action, ID: id, From: from, Time: now}
  2141. srv.AddEvent(jm)
  2142. for _, c := range srv.listeners {
  2143. select { // non blocking channel
  2144. case c <- jm:
  2145. default:
  2146. }
  2147. }
  2148. return &jm
  2149. }
  2150. func (srv *Server) AddEvent(jm utils.JSONMessage) {
  2151. srv.Lock()
  2152. defer srv.Unlock()
  2153. srv.events = append(srv.events, jm)
  2154. }
  2155. func (srv *Server) GetEvents() []utils.JSONMessage {
  2156. srv.RLock()
  2157. defer srv.RUnlock()
  2158. return srv.events
  2159. }
  2160. type Server struct {
  2161. sync.RWMutex
  2162. runtime *Runtime
  2163. pullingPool map[string]chan struct{}
  2164. pushingPool map[string]chan struct{}
  2165. events []utils.JSONMessage
  2166. listeners map[string]chan utils.JSONMessage
  2167. Eng *engine.Engine
  2168. }