This can be achived using the Docker HTTP API via curl or equivalent.
See the official documentation: https://docs.docker.com/engine/api/v1.39/#operation/ImageCreate
The Engine API is an HTTP API served by Docker Engine. It is the API
the Docker client uses to communicate with the Engine, so everything
the Docker client can do can be done with the API.
Most of the client's commands map directly to API endpoints (e.g.
docker ps is GET /containers/json). The notable exception is running
containers, which consists of several API calls.
Reverse Engineering:
First create a Unix socket for inspecting docker client requests:
socat -v UNIX-LISTEN:/tmp/fake,fork UNIX-CONNECT:/var/run/docker.sock
Next, use the docker client to run docker pull ...:
docker -H unix:///tmp/fake pull db-docker-xsrt-rt.artifactory.example.net/aquasec/kube-hunter
HTTP traffic sent between docker client and dockerd server:
> 2021/04/13 12:42:21.445593 length=80 from=0 to=79
GET /_ping HTTP/1.1\r
Host: docker\r
User-Agent: Docker-Client/18.09.6 (linux)\r
\r
< 2021/04/13 12:42:21.446085 length=212 from=0 to=211
HTTP/1.1 200 OK\r
Api-Version: 1.39\r
Docker-Experimental: false\r
Ostype: linux\r
Server: Docker/18.09.6 (linux)\r
Date: Tue, 13 Apr 2021 10:42:21 GMT\r
Content-Length: 2\r
Content-Type: text/plain; charset=utf-8\r
\r
OK> 2021/04/13 12:42:21.447291 length=401 from=80 to=480
POST /v1.39/images/create?fromImage=db-docker-xsrt-rt.artifactory.example.net%2Faquasec%2Fkube-hunter&tag=latest HTTP/1.1\r
Host: docker\r
User-Agent: Docker-Client/18.09.6 (linux)\r
Content-Length: 0\r
Content-Type: text/plain\r
X-Registry-Auth: <redacted>\r
\r
< 2021/04/13 12:42:21.546168 length=352 from=212 to=563
HTTP/1.1 200 OK\r
Api-Version: 1.39\r
Content-Type: application/json\r
Docker-Experimental: false\r
Ostype: linux\r
Server: Docker/18.09.6 (linux)\r
Date: Tue, 13 Apr 2021 10:42:21 GMT\r
Transfer-Encoding: chunked\r
\r
3d\r
{"status":"Pulling from aquasec/kube-hunter","id":"latest"}\r
\r
45\r
{"status":"Already exists","progressDetail":{},"id":"801bfaa63ef2"}\r
\r
< 2021/04/13 12:42:21.552481 length=811 from=564 to=1374
...
The relevant part is the following, where credentials from ~/docker/config.json are provided Base64 encoded via X-Registry-Auth HTTP header:
POST /v1.39/images/create?fromImage=db-docker-xsrt-rt.artifactory.example.net%2Faquasec%2Fkube-hunter&tag=latest HTTP/1.1\r
Host: docker\r
User-Agent: Docker-Client/18.09.6 (linux)\r
Content-Length: 0\r
Content-Type: text/plain\r
X-Registry-Auth: <redacted>\r
\r
Decoding the X-Registry-Auth value yields something like (redacted):
echo <redacted> | base64 -d
{"username":"<redacted","password":"<redacted>","serveraddress":"db-docker-xsrt-rt.artifactory.example.net"}