I'm not an InterSystems guy and can say only from my point of view, how it works.

Every global name has internal representation in some kind of binary format, I don't know how it can be converted to and back. But this string used to find a correct block. Like when you looking for ^C(9996,46, yellow), it first should read Map (Block 3), to find where Global ^C started (Block 44), then using this internal format for global, it can find the closest node in the first pointer block if it points to another pointer block, the same search repeats until it reached any Data block, which may also contain data for multiple nodes. 

Not sure If I can better explain it, but most important is that B* tree helps to very quickly find the final block, and their neighbours. 

Look at this my article where you will find some details, how to build Cache in docker on centos.

Instead of COPY and tar I would recommend using ADD command because it doing extract at the same time.

And for doing such build, you should have file cache-2017.1.3.317.0.18571-lnxrhx64.tar.gz close to the Dockerfile, or in the root of build context.

If you do build this way. Cache distributive should be in the current folder.

docker build .

But, you will face an issue with Storage Driver. It will look like, successful build but PROTECT error during startup. With previous versions of Docker it was possible to change Storage driver to aufs, but not with the latest version, where support for such driver already removed. There are some tricks on how to manage to work with it, but I would not recommend it.

Nowadays only IRIS 2019.1 works quite well in Docker with the default storage driver out of the box.

If you would like to do it with %Installer Manifiest, it is not going to be easy, unfortunately. CSPApplication there quite limited.

I can't just do it this way.

<CSPApplication Url="${CSPApp}" Directory="${CSPAppDir}" iKnowEnabled="yes"/>

You should first create simple csp application

<CSPApplication Url="${CSPApp}" Directory="${CSPAppDir}"/>

Add something like this method

ClassMethod EnableiKnow(pCSPName As %String = "") As %Status
{
  new $namespace
  znspace "%SYS"
  set props("iKnowEnabled")=1
  d ##class(Security.Applications).Modify(pCSPName,.props)
  quit $$$OK
}

But unfortunately, I also can't just call it from an installer, Invoke tag should be placed in Namespace tag. which is actually current namespace, but you should compute it first. This may help to declare a couple more default variables. Just place two first lines before your Installer generator

  do %code.WriteLine($c(9)_"set pVars(""CURRENTCLASS"")="""_%classname_"""")
  do %code.WriteLine($c(9)_"set pVars(""CURRENTNS"")=$namespace")
  quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "setup")

And finally, you can add this to your installer. Place it after CSPApplication creation, but outside of Namespace tag.

<Namespace Name="${CURRENTNS}">
    <Invoke Class="${CURRENTCLASS}" Method="EnableiKnow" CheckStatus="true">
      <Arg Value="${CSPAPP}"/>
    </Invoke>
  </Namespace>

I did not know about "%%UPDATE","%%INSERT". I decided to add an extra field

CREATE TABLE "test" (
  "identifier"   VARCHAR(200) NOT NULL,
  "value"        INTEGER
                 COMPUTECODE { Set {*}={*}+{increment} }
                 COMPUTEONCHANGE ("%%UPDATE","%%INSERT"),
  "increment"    INTEGER,
  PRIMARY KEY ("identifier")
)

and 

INSERT OR UPDATE INTO "test" ("identifier", "increment")
          VALUES ('someid', 1)

this solved my issue

I would not be so sure in your doubts about VSCode. VSCode itself supports refactoring staff, we just do not have it in ObjectScript extension, yet. Deleting obsolete classes, for sure very interesting and quite difficult task. But better to solve it another way, with just clean rebuild. Or for example I can add action delete in the context menu in server explorer, so, a developer will be able to manually delete any class/routine on the server from VSCode.

To activate OS authentication in your docker image, you can run this code, in %SYS namespace

Do ##class(Security.System).Get(,.p) Set p("AutheEnabled")=p("AutheEnabled")+16 Do ##class(Security.System).Modify(,.p)

If you work with community edition, you can use my image, where you can easily define also user and password for external use.

Running server

$ docker run -d --rm --name iris \
 -p 52773:52773 \
 -e IRIS_USER=test \
 -e IRIS_PASSWORD=test \
 daimor/intersystems-iris:2019.1.0S.111.0-community

Terminal connect

$ docker exec -it iris iris session iris

Node: 413a4da758e7, Instance: IRIS

USER>write $username
root
USER>write $roles
%All

Or with docker-compose, something like this

  iris:
    image: daimor/intersystems-iris:2019.1.0S.111.0-community
    ports:
      - 52773:52773
    environment:
      IRIS_USER: ${IRIS_PASSWORD:-test}
      IRIS_PASSWORD: ${IRIS_PASSWORD:-test}

You can extend UrlMap only by splitting routes

While in one class you have this

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<Route Url="/class/:namespace/:classname" Method="GET" Call="GetClass" Cors="true"/>
<Map Prefix="/something" Forward="Some.Your.Class"/>
</Routes>
}

You can add one more class, whic will work only with routes started with /something with

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<Route Url="/more" Method="GET" Call="More" Cors="true"/>
</Routes>
}

Where real route will be /something/more


  Set ht = ##class(%Net.HttpRequest).%New()
  Set ht.Server = "server"
  Do ht.SetParam("param1", "true")
  Do ht.SetHeader("myheader", "headervalue")
  Set tSC = ht.Get("/api/get", 1)

Look at the second parameter in the call of Get method, it is a test flag, helps to understand how your request will actually go

GET /api/get?param1=true HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; InterSystems IRIS;)
Host: server
Accept-Encoding: gzip
myheader: headervalue

Look at this code, it will do the same


  Set ht = ##class(%Net.HttpRequest).%New()
  Set ht.Server = "server"
  Do ht.SetParam("param1", "true")
  Do ht.SetHeader("myheader", "headervalue")
  Set ht.Location = "/api/get"
  Set tSC = ht.Get(, 1)

Or even this code


  Set ht = ##class(%Net.HttpRequest).%New()
  Do ht.SetHeader("myheader", "headervalue")
  Set tSC = ht.Get("http://server/api/get?param1=true", 1)

You can find them in the source of README

[![](https://img.shields.io/badge/InterSystems-IRIS-blue.svg)](https://www.intersystems.com/products/intersystems-iris/)
[![](https://img.shields.io/badge/InterSystems-Caché-blue.svg)](https://www.intersystems.com/products/cache/)
[![](https://img.shields.io/badge/InterSystems-Ensemble-blue.svg)](https://www.intersystems.com/products/ensemble/)