support for remote APP_ARCHIVE, with self-contained Dockerfile (e.g. for Docker Hub);
authorwenzelm
Mon, 16 Jan 2017 16:00:34 +0100
changeset 64905 5e2eb9b14bbe
parent 64904 14c760e0e1cf
child 64906 49549acbf025
support for remote APP_ARCHIVE, with self-contained Dockerfile (e.g. for Docker Hub);
src/Pure/Admin/build_docker.scala
--- a/src/Pure/Admin/build_docker.scala	Mon Jan 16 15:50:54 2017 +0100
+++ b/src/Pure/Admin/build_docker.scala	Mon Jan 16 16:00:34 2017 +0100
@@ -11,6 +11,8 @@
 {
   private lazy val default_logic = Isabelle_System.getenv("ISABELLE_LOGIC")
 
+  private val Isabelle_Name = """^.*?(Isabelle[^/\\:]+)_(?:app|linux)\.tar\.gz$""".r
+
   val packages: List[String] =
     List("curl", "less", "lib32stdc++6", "libgomp1", "libwww-perl", "rlwrap", "unzip")
 
@@ -19,31 +21,29 @@
       "latex" -> List("texlive-fonts-extra", "texlive-latex-extra", "texlive-math-extra"))
 
   def build_docker(progress: Progress,
-    app_archive: Path,
+    app_archive: String,
     logic: String = default_logic,
     output: Option[Path] = None,
     more_packages: List[String] = Nil,
     tag: String = "",
     verbose: Boolean = false)
   {
-    val distname =
-    {
-      val Name = "^(Isabelle[^/]*)/?.*$".r
-      Isabelle_System.bash("tar tzf " + File.bash_path(app_archive)).check.out_lines match {
-        case Name(name) :: _ => name
+    val isabelle_name =
+      app_archive match {
+        case Isabelle_Name(name) => name
         case _ => error("Cannot determine Isabelle distribution name from " + app_archive)
       }
-    }
+    val is_remote = Url.is_wellformed(app_archive)
 
     val dockerfile =
-      """## Dockerfile for """ + distname + """
+      """## Dockerfile for """ + isabelle_name + """
 
 FROM ubuntu
 SHELL ["/bin/bash", "-c"]
 
 # packages
 RUN apt-get -y update && \
-  apt-get install -y  """ + (packages ::: more_packages).map(Bash.string(_)).mkString(" ") + """ && \
+  apt-get install -y """ + (packages ::: more_packages).map(Bash.string(_)).mkString(" ") + """ && \
   apt-get clean
 
 # user
@@ -52,9 +52,13 @@
 
 # Isabelle
 WORKDIR /home/isabelle
-COPY Isabelle.tar.gz .
+""" +
+ (if (is_remote)
+   "RUN curl --fail --silent " + Bash.string(app_archive) + " > Isabelle.tar.gz"
+  else "COPY Isabelle.tar.gz .") +
+"""
 RUN tar xzf Isabelle.tar.gz && \
-  mv """ + distname + """ Isabelle && \
+  mv """ + isabelle_name + """ Isabelle && \
   rm -rf Isabelle.tar.gz Isabelle/contrib/jdk/x86-linux && \
   perl -pi -e 's,ISABELLE_HOME_USER=.*,ISABELLE_HOME_USER="\$USER_HOME/.isabelle",g;' Isabelle/etc/settings && \
   perl -pi -e 's,ISABELLE_LOGIC=.*,ISABELLE_LOGIC=""" + logic + """,g;' Isabelle/etc/settings && \
@@ -68,7 +72,12 @@
     Isabelle_System.with_tmp_dir("docker")(tmp_dir =>
       {
         File.write(tmp_dir + Path.explode("Dockerfile"), dockerfile)
-        File.copy(app_archive, tmp_dir + Path.explode("Isabelle.tar.gz"))
+
+        if (is_remote) {
+          if (!Url.is_readable(app_archive))
+            error("Cannot access remote archive " + app_archive)
+        }
+        else File.copy(Path.explode(app_archive), tmp_dir + Path.explode("Isabelle.tar.gz"))
 
         val quiet_option = if (verbose) "" else " -q"
         val tag_option = if (tag == "") "" else " -t " + Bash.string(tag)
@@ -103,11 +112,14 @@
     -v           verbose
 
   Build Isabelle docker image with default logic image, using a standard
-  Isabelle application archive for Linux.
+  Isabelle application archive for Linux (local file or remote URL).
 
-  Example:
+  Examples:
 
     isabelle build_docker -t test/isabelle:Isabelle2016-1 Isabelle2016-1_app.tar.gz
+
+    isabelle build_docker -t test/isabelle:Isabelle2016-1 -o Dockerfile http://isabelle.in.tum.de/dist/Isabelle2016-1_app.tar.gz
+
 """,
           "P:" -> (arg =>
             package_collections.get(arg) match {
@@ -123,7 +135,7 @@
       val more_args = getopts(args)
       val app_archive =
         more_args match {
-          case List(arg) => Path.explode(arg)
+          case List(arg) => arg
           case _ => getopts.usage()
         }