server.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. package docker
  2. import (
  3. "fmt"
  4. "github.com/dotcloud/docker/auth"
  5. "github.com/dotcloud/docker/registry"
  6. "github.com/dotcloud/docker/utils"
  7. "io"
  8. "io/ioutil"
  9. "log"
  10. "net/http"
  11. "net/url"
  12. "os"
  13. "path"
  14. "runtime"
  15. "strings"
  16. )
  17. func (srv *Server) DockerVersion() APIVersion {
  18. return APIVersion{
  19. Version: VERSION,
  20. GitCommit: GITCOMMIT,
  21. GoVersion: runtime.Version(),
  22. }
  23. }
  24. func (srv *Server) ContainerKill(name string) error {
  25. if container := srv.runtime.Get(name); container != nil {
  26. if err := container.Kill(); err != nil {
  27. return fmt.Errorf("Error restarting container %s: %s", name, err.Error())
  28. }
  29. } else {
  30. return fmt.Errorf("No such container: %s", name)
  31. }
  32. return nil
  33. }
  34. func (srv *Server) ContainerExport(name string, out io.Writer) error {
  35. if container := srv.runtime.Get(name); container != nil {
  36. data, err := container.Export()
  37. if err != nil {
  38. return err
  39. }
  40. // Stream the entire contents of the container (basically a volatile snapshot)
  41. if _, err := io.Copy(out, data); err != nil {
  42. return err
  43. }
  44. return nil
  45. }
  46. return fmt.Errorf("No such container: %s", name)
  47. }
  48. func (srv *Server) ImagesSearch(term string) ([]APISearch, error) {
  49. results, err := registry.NewRegistry(srv.runtime.root).SearchRepositories(term)
  50. if err != nil {
  51. return nil, err
  52. }
  53. var outs []APISearch
  54. for _, repo := range results.Results {
  55. var out APISearch
  56. out.Description = repo["description"]
  57. if len(out.Description) > 45 {
  58. out.Description = utils.Trunc(out.Description, 42) + "..."
  59. }
  60. out.Name = repo["name"]
  61. outs = append(outs, out)
  62. }
  63. return outs, nil
  64. }
  65. func (srv *Server) ImageInsert(name, url, path string, out io.Writer, sf *utils.StreamFormatter) (string, error) {
  66. out = utils.NewWriteFlusher(out)
  67. img, err := srv.runtime.repositories.LookupImage(name)
  68. if err != nil {
  69. return "", err
  70. }
  71. file, err := utils.Download(url, out)
  72. if err != nil {
  73. return "", err
  74. }
  75. defer file.Body.Close()
  76. config, _, err := ParseRun([]string{img.ID, "echo", "insert", url, path}, srv.runtime.capabilities)
  77. if err != nil {
  78. return "", err
  79. }
  80. b := NewBuilder(srv.runtime)
  81. c, err := b.Create(config)
  82. if err != nil {
  83. return "", err
  84. }
  85. if err := c.Inject(utils.ProgressReader(file.Body, int(file.ContentLength), out, sf.FormatProgress("Downloading", "%v/%v (%v)"), sf), path); err != nil {
  86. return "", err
  87. }
  88. // FIXME: Handle custom repo, tag comment, author
  89. img, err = b.Commit(c, "", "", img.Comment, img.Author, nil)
  90. if err != nil {
  91. return "", err
  92. }
  93. out.Write(sf.FormatStatus(img.ID))
  94. return img.ShortID(), nil
  95. }
  96. func (srv *Server) ImagesViz(out io.Writer) error {
  97. images, _ := srv.runtime.graph.All()
  98. if images == nil {
  99. return nil
  100. }
  101. out.Write([]byte("digraph docker {\n"))
  102. var (
  103. parentImage *Image
  104. err error
  105. )
  106. for _, image := range images {
  107. parentImage, err = image.GetParent()
  108. if err != nil {
  109. return fmt.Errorf("Error while getting parent image: %v", err)
  110. }
  111. if parentImage != nil {
  112. out.Write([]byte(" \"" + parentImage.ShortID() + "\" -> \"" + image.ShortID() + "\"\n"))
  113. } else {
  114. out.Write([]byte(" base -> \"" + image.ShortID() + "\" [style=invis]\n"))
  115. }
  116. }
  117. reporefs := make(map[string][]string)
  118. for name, repository := range srv.runtime.repositories.Repositories {
  119. for tag, id := range repository {
  120. reporefs[utils.TruncateID(id)] = append(reporefs[utils.TruncateID(id)], fmt.Sprintf("%s:%s", name, tag))
  121. }
  122. }
  123. for id, repos := range reporefs {
  124. out.Write([]byte(" \"" + id + "\" [label=\"" + id + "\\n" + strings.Join(repos, "\\n") + "\",shape=box,fillcolor=\"paleturquoise\",style=\"filled,rounded\"];\n"))
  125. }
  126. out.Write([]byte(" base [style=invisible]\n}\n"))
  127. return nil
  128. }
  129. func (srv *Server) Images(all bool, filter string) ([]APIImages, error) {
  130. var (
  131. allImages map[string]*Image
  132. err error
  133. )
  134. if all {
  135. allImages, err = srv.runtime.graph.Map()
  136. } else {
  137. allImages, err = srv.runtime.graph.Heads()
  138. }
  139. if err != nil {
  140. return nil, err
  141. }
  142. outs := []APIImages{} //produce [] when empty instead of 'null'
  143. for name, repository := range srv.runtime.repositories.Repositories {
  144. if filter != "" && name != filter {
  145. continue
  146. }
  147. for tag, id := range repository {
  148. var out APIImages
  149. image, err := srv.runtime.graph.Get(id)
  150. if err != nil {
  151. log.Printf("Warning: couldn't load %s from %s/%s: %s", id, name, tag, err)
  152. continue
  153. }
  154. delete(allImages, id)
  155. out.Repository = name
  156. out.Tag = tag
  157. out.ID = image.ID
  158. out.Created = image.Created.Unix()
  159. outs = append(outs, out)
  160. }
  161. }
  162. // Display images which aren't part of a
  163. if filter == "" {
  164. for _, image := range allImages {
  165. var out APIImages
  166. out.ID = image.ID
  167. out.Created = image.Created.Unix()
  168. outs = append(outs, out)
  169. }
  170. }
  171. return outs, nil
  172. }
  173. func (srv *Server) DockerInfo() *APIInfo {
  174. images, _ := srv.runtime.graph.All()
  175. var imgcount int
  176. if images == nil {
  177. imgcount = 0
  178. } else {
  179. imgcount = len(images)
  180. }
  181. return &APIInfo{
  182. Containers: len(srv.runtime.List()),
  183. Images: imgcount,
  184. MemoryLimit: srv.runtime.capabilities.MemoryLimit,
  185. SwapLimit: srv.runtime.capabilities.SwapLimit,
  186. Debug: os.Getenv("DEBUG") != "",
  187. NFd: utils.GetTotalUsedFds(),
  188. NGoroutines: runtime.NumGoroutine(),
  189. }
  190. }
  191. func (srv *Server) ImageHistory(name string) ([]APIHistory, error) {
  192. image, err := srv.runtime.repositories.LookupImage(name)
  193. if err != nil {
  194. return nil, err
  195. }
  196. outs := []APIHistory{} //produce [] when empty instead of 'null'
  197. err = image.WalkHistory(func(img *Image) error {
  198. var out APIHistory
  199. out.ID = srv.runtime.repositories.ImageName(img.ShortID())
  200. out.Created = img.Created.Unix()
  201. out.CreatedBy = strings.Join(img.ContainerConfig.Cmd, " ")
  202. outs = append(outs, out)
  203. return nil
  204. })
  205. return outs, nil
  206. }
  207. func (srv *Server) ContainerChanges(name string) ([]Change, error) {
  208. if container := srv.runtime.Get(name); container != nil {
  209. return container.Changes()
  210. }
  211. return nil, fmt.Errorf("No such container: %s", name)
  212. }
  213. func (srv *Server) Containers(all bool, n int, since, before string) []APIContainers {
  214. var foundBefore bool
  215. var displayed int
  216. retContainers := []APIContainers{}
  217. for _, container := range srv.runtime.List() {
  218. if !container.State.Running && !all && n == -1 && since == "" && before == "" {
  219. continue
  220. }
  221. if before != "" {
  222. if container.ShortID() == before {
  223. foundBefore = true
  224. continue
  225. }
  226. if !foundBefore {
  227. continue
  228. }
  229. }
  230. if displayed == n {
  231. break
  232. }
  233. if container.ShortID() == since {
  234. break
  235. }
  236. displayed++
  237. c := APIContainers{
  238. ID: container.ID,
  239. }
  240. c.Image = srv.runtime.repositories.ImageName(container.Image)
  241. c.Command = fmt.Sprintf("%s %s", container.Path, strings.Join(container.Args, " "))
  242. c.Created = container.Created.Unix()
  243. c.Status = container.State.String()
  244. c.Ports = container.NetworkSettings.PortMappingHuman()
  245. retContainers = append(retContainers, c)
  246. }
  247. return retContainers
  248. }
  249. func (srv *Server) ContainerCommit(name, repo, tag, author, comment string, config *Config) (string, error) {
  250. container := srv.runtime.Get(name)
  251. if container == nil {
  252. return "", fmt.Errorf("No such container: %s", name)
  253. }
  254. img, err := NewBuilder(srv.runtime).Commit(container, repo, tag, comment, author, config)
  255. if err != nil {
  256. return "", err
  257. }
  258. return img.ShortID(), err
  259. }
  260. func (srv *Server) ContainerTag(name, repo, tag string, force bool) error {
  261. if err := srv.runtime.repositories.Set(repo, tag, name, force); err != nil {
  262. return err
  263. }
  264. return nil
  265. }
  266. func (srv *Server) pullImage(r *registry.Registry, out io.Writer, imgId, endpoint string, token []string, sf *utils.StreamFormatter) error {
  267. history, err := r.GetRemoteHistory(imgId, endpoint, token)
  268. if err != nil {
  269. return err
  270. }
  271. // FIXME: Try to stream the images?
  272. // FIXME: Launch the getRemoteImage() in goroutines
  273. for _, id := range history {
  274. if !srv.runtime.graph.Exists(id) {
  275. out.Write(sf.FormatStatus("Pulling %s metadata", id))
  276. imgJSON, err := r.GetRemoteImageJSON(id, endpoint, token)
  277. if err != nil {
  278. // FIXME: Keep goging in case of error?
  279. return err
  280. }
  281. img, err := NewImgJSON(imgJSON)
  282. if err != nil {
  283. return fmt.Errorf("Failed to parse json: %s", err)
  284. }
  285. // Get the layer
  286. out.Write(sf.FormatStatus("Pulling %s fs layer", id))
  287. layer, contentLength, err := r.GetRemoteImageLayer(img.ID, endpoint, token)
  288. if err != nil {
  289. return err
  290. }
  291. defer layer.Close()
  292. if err := srv.runtime.graph.Register(utils.ProgressReader(layer, contentLength, out, sf.FormatProgress("Downloading", "%v/%v (%v)"), sf), false, img); err != nil {
  293. return err
  294. }
  295. }
  296. }
  297. return nil
  298. }
  299. func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, remote, askedTag string, sf *utils.StreamFormatter) error {
  300. out.Write(sf.FormatStatus("Pulling repository %s from %s", remote, auth.IndexServerAddress()))
  301. repoData, err := r.GetRepositoryData(remote)
  302. if err != nil {
  303. return err
  304. }
  305. utils.Debugf("Updating checksums")
  306. // Reload the json file to make sure not to overwrite faster sums
  307. if err := srv.runtime.graph.UpdateChecksums(repoData.ImgList); err != nil {
  308. return err
  309. }
  310. utils.Debugf("Retrieving the tag list")
  311. tagsList, err := r.GetRemoteTags(repoData.Endpoints, remote, repoData.Tokens)
  312. if err != nil {
  313. return err
  314. }
  315. utils.Debugf("Registering tags")
  316. // If not specific tag have been asked, take all
  317. if askedTag == "" {
  318. for tag, id := range tagsList {
  319. repoData.ImgList[id].Tag = tag
  320. }
  321. } else {
  322. // Otherwise, check that the tag exists and use only that one
  323. id, exists := tagsList[askedTag]
  324. if !exists {
  325. return fmt.Errorf("Tag %s not found in repositoy %s", askedTag, remote)
  326. }
  327. repoData.ImgList[id].Tag = askedTag
  328. }
  329. for _, img := range repoData.ImgList {
  330. if askedTag != "" && img.Tag != askedTag {
  331. utils.Debugf("(%s) does not match %s (id: %s), skipping", img.Tag, askedTag, img.ID)
  332. continue
  333. }
  334. out.Write(sf.FormatStatus("Pulling image %s (%s) from %s", img.ID, img.Tag, remote))
  335. success := false
  336. for _, ep := range repoData.Endpoints {
  337. if err := srv.pullImage(r, out, img.ID, "https://"+ep+"/v1", repoData.Tokens, sf); err != nil {
  338. out.Write(sf.FormatStatus("Error while retrieving image for tag: %s (%s); checking next endpoint", askedTag, err))
  339. continue
  340. }
  341. success = true
  342. break
  343. }
  344. if !success {
  345. return fmt.Errorf("Could not find repository on any of the indexed registries.")
  346. }
  347. }
  348. for tag, id := range tagsList {
  349. if askedTag != "" && tag != askedTag {
  350. continue
  351. }
  352. if err := srv.runtime.repositories.Set(remote, tag, id, true); err != nil {
  353. return err
  354. }
  355. }
  356. if err := srv.runtime.repositories.Save(); err != nil {
  357. return err
  358. }
  359. return nil
  360. }
  361. func (srv *Server) ImagePull(name, tag, endpoint string, out io.Writer, sf *utils.StreamFormatter) error {
  362. r := registry.NewRegistry(srv.runtime.root)
  363. out = utils.NewWriteFlusher(out)
  364. if endpoint != "" {
  365. if err := srv.pullImage(r, out, name, endpoint, nil, sf); err != nil {
  366. return err
  367. }
  368. return nil
  369. }
  370. if err := srv.pullRepository(r, out, name, tag, sf); err != nil {
  371. return err
  372. }
  373. return nil
  374. }
  375. // Retrieve the checksum of an image
  376. // Priority:
  377. // - Check on the stored checksums
  378. // - Check if the archive exists, if it does not, ask the registry
  379. // - If the archive does exists, process the checksum from it
  380. // - If the archive does not exists and not found on registry, process checksum from layer
  381. func (srv *Server) getChecksum(imageId string) (string, error) {
  382. // FIXME: Use in-memory map instead of reading the file each time
  383. if sums, err := srv.runtime.graph.getStoredChecksums(); err != nil {
  384. return "", err
  385. } else if checksum, exists := sums[imageId]; exists {
  386. return checksum, nil
  387. }
  388. img, err := srv.runtime.graph.Get(imageId)
  389. if err != nil {
  390. return "", err
  391. }
  392. if _, err := os.Stat(layerArchivePath(srv.runtime.graph.imageRoot(imageId))); err != nil {
  393. if os.IsNotExist(err) {
  394. // TODO: Ask the registry for the checksum
  395. // As the archive is not there, it is supposed to come from a pull.
  396. } else {
  397. return "", err
  398. }
  399. }
  400. checksum, err := img.Checksum()
  401. if err != nil {
  402. return "", err
  403. }
  404. return checksum, nil
  405. }
  406. // Retrieve the all the images to be uploaded in the correct order
  407. // Note: we can't use a map as it is not ordered
  408. func (srv *Server) getImageList(localRepo map[string]string) ([]*registry.ImgData, error) {
  409. var imgList []*registry.ImgData
  410. imageSet := make(map[string]struct{})
  411. for tag, id := range localRepo {
  412. img, err := srv.runtime.graph.Get(id)
  413. if err != nil {
  414. return nil, err
  415. }
  416. img.WalkHistory(func(img *Image) error {
  417. if _, exists := imageSet[img.ID]; exists {
  418. return nil
  419. }
  420. imageSet[img.ID] = struct{}{}
  421. checksum, err := srv.getChecksum(img.ID)
  422. if err != nil {
  423. return err
  424. }
  425. imgList = append([]*registry.ImgData{{
  426. ID: img.ID,
  427. Checksum: checksum,
  428. Tag: tag,
  429. }}, imgList...)
  430. return nil
  431. })
  432. }
  433. return imgList, nil
  434. }
  435. func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, name string, localRepo map[string]string, sf *utils.StreamFormatter) error {
  436. out = utils.NewWriteFlusher(out)
  437. out.Write(sf.FormatStatus("Processing checksums"))
  438. imgList, err := srv.getImageList(localRepo)
  439. if err != nil {
  440. return err
  441. }
  442. out.Write(sf.FormatStatus("Sending image list"))
  443. repoData, err := r.PushImageJSONIndex(name, imgList, false, nil)
  444. if err != nil {
  445. return err
  446. }
  447. for _, ep := range repoData.Endpoints {
  448. out.Write(sf.FormatStatus("Pushing repository %s to %s (%d tags)", name, ep, len(localRepo)))
  449. // For each image within the repo, push them
  450. for _, elem := range imgList {
  451. if _, exists := repoData.ImgList[elem.ID]; exists {
  452. out.Write(sf.FormatStatus("Image %s already on registry, skipping", name))
  453. continue
  454. }
  455. if err := srv.pushImage(r, out, name, elem.ID, ep, repoData.Tokens, sf); err != nil {
  456. // FIXME: Continue on error?
  457. return err
  458. }
  459. out.Write(sf.FormatStatus("Pushing tags for rev [%s] on {%s}", elem.ID, ep+"/users/"+name+"/"+elem.Tag))
  460. if err := r.PushRegistryTag(name, elem.ID, elem.Tag, ep, repoData.Tokens); err != nil {
  461. return err
  462. }
  463. }
  464. }
  465. if _, err := r.PushImageJSONIndex(name, imgList, true, repoData.Endpoints); err != nil {
  466. return err
  467. }
  468. return nil
  469. }
  470. func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgId, ep string, token []string, sf *utils.StreamFormatter) error {
  471. out = utils.NewWriteFlusher(out)
  472. jsonRaw, err := ioutil.ReadFile(path.Join(srv.runtime.graph.Root, imgId, "json"))
  473. if err != nil {
  474. return fmt.Errorf("Error while retreiving the path for {%s}: %s", imgId, err)
  475. }
  476. out.Write(sf.FormatStatus("Pushing %s", imgId))
  477. // Make sure we have the image's checksum
  478. checksum, err := srv.getChecksum(imgId)
  479. if err != nil {
  480. return err
  481. }
  482. imgData := &registry.ImgData{
  483. ID: imgId,
  484. Checksum: checksum,
  485. }
  486. // Send the json
  487. if err := r.PushImageJSONRegistry(imgData, jsonRaw, ep, token); err != nil {
  488. if err == registry.ErrAlreadyExists {
  489. out.Write(sf.FormatStatus("Image %s already uploaded ; skipping", imgData.ID))
  490. return nil
  491. }
  492. return err
  493. }
  494. // Retrieve the tarball to be sent
  495. var layerData *TempArchive
  496. // If the archive exists, use it
  497. file, err := os.Open(layerArchivePath(srv.runtime.graph.imageRoot(imgId)))
  498. if err != nil {
  499. if os.IsNotExist(err) {
  500. // If the archive does not exist, create one from the layer
  501. layerData, err = srv.runtime.graph.TempLayerArchive(imgId, Xz, out)
  502. if err != nil {
  503. return fmt.Errorf("Failed to generate layer archive: %s", err)
  504. }
  505. } else {
  506. return err
  507. }
  508. } else {
  509. defer file.Close()
  510. st, err := file.Stat()
  511. if err != nil {
  512. return err
  513. }
  514. layerData = &TempArchive{
  515. File: file,
  516. Size: st.Size(),
  517. }
  518. }
  519. // Send the layer
  520. if err := r.PushImageLayerRegistry(imgData.ID, utils.ProgressReader(layerData, int(layerData.Size), out, sf.FormatProgress("Pushing", "%v/%v (%v)"), sf), ep, token); err != nil {
  521. return err
  522. }
  523. return nil
  524. }
  525. func (srv *Server) ImagePush(name, endpoint string, out io.Writer, sf *utils.StreamFormatter) error {
  526. out = utils.NewWriteFlusher(out)
  527. img, err := srv.runtime.graph.Get(name)
  528. r := registry.NewRegistry(srv.runtime.root)
  529. if err != nil {
  530. out.Write(sf.FormatStatus("The push refers to a repository [%s] (len: %d)", name, len(srv.runtime.repositories.Repositories[name])))
  531. // If it fails, try to get the repository
  532. if localRepo, exists := srv.runtime.repositories.Repositories[name]; exists {
  533. if err := srv.pushRepository(r, out, name, localRepo, sf); err != nil {
  534. return err
  535. }
  536. return nil
  537. }
  538. return err
  539. }
  540. out.Write(sf.FormatStatus("The push refers to an image: [%s]", name))
  541. if err := srv.pushImage(r, out, name, img.ID, endpoint, nil, sf); err != nil {
  542. return err
  543. }
  544. return nil
  545. }
  546. func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Writer, sf *utils.StreamFormatter) error {
  547. var archive io.Reader
  548. var resp *http.Response
  549. if src == "-" {
  550. archive = in
  551. } else {
  552. u, err := url.Parse(src)
  553. if err != nil {
  554. return err
  555. }
  556. if u.Scheme == "" {
  557. u.Scheme = "http"
  558. u.Host = src
  559. u.Path = ""
  560. }
  561. out.Write(sf.FormatStatus("Downloading from %s", u))
  562. // Download with curl (pretty progress bar)
  563. // If curl is not available, fallback to http.Get()
  564. resp, err = utils.Download(u.String(), out)
  565. if err != nil {
  566. return err
  567. }
  568. archive = utils.ProgressReader(resp.Body, int(resp.ContentLength), out, sf.FormatProgress("Importing", "%v/%v (%v)"), sf)
  569. }
  570. img, err := srv.runtime.graph.Create(archive, nil, "Imported from "+src, "", nil)
  571. if err != nil {
  572. return err
  573. }
  574. // Optionally register the image at REPO/TAG
  575. if repo != "" {
  576. if err := srv.runtime.repositories.Set(repo, tag, img.ID, true); err != nil {
  577. return err
  578. }
  579. }
  580. out.Write(sf.FormatStatus(img.ShortID()))
  581. return nil
  582. }
  583. func (srv *Server) ContainerCreate(config *Config) (string, error) {
  584. if config.Memory > 0 && !srv.runtime.capabilities.MemoryLimit {
  585. config.Memory = 0
  586. }
  587. if config.Memory > 0 && !srv.runtime.capabilities.SwapLimit {
  588. config.MemorySwap = -1
  589. }
  590. b := NewBuilder(srv.runtime)
  591. container, err := b.Create(config)
  592. if err != nil {
  593. if srv.runtime.graph.IsNotExist(err) {
  594. return "", fmt.Errorf("No such image: %s", config.Image)
  595. }
  596. return "", err
  597. }
  598. return container.ShortID(), nil
  599. }
  600. func (srv *Server) ContainerRestart(name string, t int) error {
  601. if container := srv.runtime.Get(name); container != nil {
  602. if err := container.Restart(t); err != nil {
  603. return fmt.Errorf("Error restarting container %s: %s", name, err.Error())
  604. }
  605. } else {
  606. return fmt.Errorf("No such container: %s", name)
  607. }
  608. return nil
  609. }
  610. func (srv *Server) ContainerDestroy(name string, removeVolume bool) error {
  611. if container := srv.runtime.Get(name); container != nil {
  612. volumes := make(map[string]struct{})
  613. // Store all the deleted containers volumes
  614. for _, volumeId := range container.Volumes {
  615. volumes[volumeId] = struct{}{}
  616. }
  617. if err := srv.runtime.Destroy(container); err != nil {
  618. return fmt.Errorf("Error destroying container %s: %s", name, err.Error())
  619. }
  620. if removeVolume {
  621. // Retrieve all volumes from all remaining containers
  622. usedVolumes := make(map[string]*Container)
  623. for _, container := range srv.runtime.List() {
  624. for _, containerVolumeId := range container.Volumes {
  625. usedVolumes[containerVolumeId] = container
  626. }
  627. }
  628. for volumeId := range volumes {
  629. // If the requested volu
  630. if c, exists := usedVolumes[volumeId]; exists {
  631. log.Printf("The volume %s is used by the container %s. Impossible to remove it. Skipping.\n", volumeId, c.ID)
  632. continue
  633. }
  634. if err := srv.runtime.volumes.Delete(volumeId); err != nil {
  635. return err
  636. }
  637. }
  638. }
  639. } else {
  640. return fmt.Errorf("No such container: %s", name)
  641. }
  642. return nil
  643. }
  644. func (srv *Server) ImageDelete(name string) error {
  645. img, err := srv.runtime.repositories.LookupImage(name)
  646. if err != nil {
  647. return fmt.Errorf("No such image: %s", name)
  648. }
  649. if err := srv.runtime.graph.Delete(img.ID); err != nil {
  650. return fmt.Errorf("Error deleting image %s: %s", name, err.Error())
  651. }
  652. return nil
  653. }
  654. func (srv *Server) ImageGetCached(imgId string, config *Config) (*Image, error) {
  655. // Retrieve all images
  656. images, err := srv.runtime.graph.All()
  657. if err != nil {
  658. return nil, err
  659. }
  660. // Store the tree in a map of map (map[parentId][childId])
  661. imageMap := make(map[string]map[string]struct{})
  662. for _, img := range images {
  663. if _, exists := imageMap[img.Parent]; !exists {
  664. imageMap[img.Parent] = make(map[string]struct{})
  665. }
  666. imageMap[img.Parent][img.ID] = struct{}{}
  667. }
  668. // Loop on the children of the given image and check the config
  669. for elem := range imageMap[imgId] {
  670. img, err := srv.runtime.graph.Get(elem)
  671. if err != nil {
  672. return nil, err
  673. }
  674. if CompareConfig(&img.ContainerConfig, config) {
  675. return img, nil
  676. }
  677. }
  678. return nil, nil
  679. }
  680. func (srv *Server) ContainerStart(name string) error {
  681. if container := srv.runtime.Get(name); container != nil {
  682. if err := container.Start(); err != nil {
  683. return fmt.Errorf("Error starting container %s: %s", name, err.Error())
  684. }
  685. } else {
  686. return fmt.Errorf("No such container: %s", name)
  687. }
  688. return nil
  689. }
  690. func (srv *Server) ContainerStop(name string, t int) error {
  691. if container := srv.runtime.Get(name); container != nil {
  692. if err := container.Stop(t); err != nil {
  693. return fmt.Errorf("Error stopping container %s: %s", name, err.Error())
  694. }
  695. } else {
  696. return fmt.Errorf("No such container: %s", name)
  697. }
  698. return nil
  699. }
  700. func (srv *Server) ContainerWait(name string) (int, error) {
  701. if container := srv.runtime.Get(name); container != nil {
  702. return container.Wait(), nil
  703. }
  704. return 0, fmt.Errorf("No such container: %s", name)
  705. }
  706. func (srv *Server) ContainerResize(name string, h, w int) error {
  707. if container := srv.runtime.Get(name); container != nil {
  708. return container.Resize(h, w)
  709. }
  710. return fmt.Errorf("No such container: %s", name)
  711. }
  712. func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, stderr bool, in io.ReadCloser, out io.Writer) error {
  713. container := srv.runtime.Get(name)
  714. if container == nil {
  715. return fmt.Errorf("No such container: %s", name)
  716. }
  717. //logs
  718. if logs {
  719. if stdout {
  720. cLog, err := container.ReadLog("stdout")
  721. if err != nil {
  722. utils.Debugf(err.Error())
  723. } else if _, err := io.Copy(out, cLog); err != nil {
  724. utils.Debugf(err.Error())
  725. }
  726. }
  727. if stderr {
  728. cLog, err := container.ReadLog("stderr")
  729. if err != nil {
  730. utils.Debugf(err.Error())
  731. } else if _, err := io.Copy(out, cLog); err != nil {
  732. utils.Debugf(err.Error())
  733. }
  734. }
  735. }
  736. //stream
  737. if stream {
  738. if container.State.Ghost {
  739. return fmt.Errorf("Impossible to attach to a ghost container")
  740. }
  741. if !container.State.Running {
  742. return fmt.Errorf("Impossible to attach to a stopped container, start it first")
  743. }
  744. var (
  745. cStdin io.ReadCloser
  746. cStdout, cStderr io.Writer
  747. cStdinCloser io.Closer
  748. )
  749. if stdin {
  750. r, w := io.Pipe()
  751. go func() {
  752. defer w.Close()
  753. defer utils.Debugf("Closing buffered stdin pipe")
  754. io.Copy(w, in)
  755. }()
  756. cStdin = r
  757. cStdinCloser = in
  758. }
  759. if stdout {
  760. cStdout = out
  761. }
  762. if stderr {
  763. cStderr = out
  764. }
  765. <-container.Attach(cStdin, cStdinCloser, cStdout, cStderr)
  766. // If we are in stdinonce mode, wait for the process to end
  767. // otherwise, simply return
  768. if container.Config.StdinOnce && !container.Config.Tty {
  769. container.Wait()
  770. }
  771. }
  772. return nil
  773. }
  774. func (srv *Server) ContainerInspect(name string) (*Container, error) {
  775. if container := srv.runtime.Get(name); container != nil {
  776. return container, nil
  777. }
  778. return nil, fmt.Errorf("No such container: %s", name)
  779. }
  780. func (srv *Server) ImageInspect(name string) (*Image, error) {
  781. if image, err := srv.runtime.repositories.LookupImage(name); err == nil && image != nil {
  782. return image, nil
  783. }
  784. return nil, fmt.Errorf("No such image: %s", name)
  785. }
  786. func NewServer(autoRestart bool) (*Server, error) {
  787. if runtime.GOARCH != "amd64" {
  788. log.Fatalf("The docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.", runtime.GOARCH)
  789. }
  790. runtime, err := NewRuntime(autoRestart)
  791. if err != nil {
  792. return nil, err
  793. }
  794. srv := &Server{
  795. runtime: runtime,
  796. }
  797. runtime.srv = srv
  798. return srv, nil
  799. }
  800. type Server struct {
  801. runtime *Runtime
  802. }