server.go 67 KB

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