I'm using go template to extract the information from "docker info" command in the json format.
I'm using following command:
[root#localhost ~]# docker info --format '{{json .CpuCfsPeriod}}'
I'm getting following error:
template: :1:7: executing "" at <.CpuCfsPeriod>: can't evaluate field CpuCfsPeriod in type types.Info
What could be the reason of this erro?
I'm able to extract other information using same kind of command,
e.g.
[root#localhost ~]# docker info --format '{{json .Debug}}'
false
It seems to be an unexpected behavior.
The struct is tagged as shown below:
type Info struct {
ID string
CPUCfsPeriod bool `json:"CpuCfsPeriod"`
}
And the field name it's properly displayed when you list the json properties using --format '{{json .}}.
But the only way you can access that property is using the struct field name.
docker info --format '{{json .CPUCfsPeriod}}'
Related
Regctl provides - among other things - a CLI for listing image tags available on a registry, but when the image has a lot of tags, pagination gets in the way.
The problem is that so far I've not found a way to obtain other than the 1st 50 tags on quay.io.
i.e. if I get tags for calico/node image from dockerhub I get
/tmp$ regctl tag ls calico/node | wc -l
8225
but when it comes to quay.io it seems to return just the first 50 tags, that is why regctl provides a specific flag (from regctl tag ls --help)
--last string Specify the last tag from a previous request for pagination
but the --last param seems not working on quay as regctl seems to return the very same contents as when invoked without the flag
/tmp$ regctl tag ls quay.io/calico/node | wc -l
50
/tmp$ regctl tag ls quay.io/calico/node | tail -n 3
v3.4.0-0.dev-27-g319e739-ppc64le
v3.4.0-0.dev-28-g909229b-amd64
v3.4.0-0.dev-28-g909229b-arm64
/tmp$ regctl tag ls quay.io/calico/node --last 'v3.4.0-0.dev-28-g909229b-arm64' | tail -n 3
v3.4.0-0.dev-27-g319e739-ppc64le
v3.4.0-0.dev-28-g909229b-amd64
v3.4.0-0.dev-28-g909229b-arm64
The parameter is working, but only kinda:
$ regctl tag ls quay.io/calico/node --last v3.3.0-4-g70e7d79-ppc64le --limit 5
v3.3.0-2-g441d7c2-arm64
v3.4.0-0.dev-25-g17db8bd
v3.4.0-0.dev-25-g17db8bd-amd64
v3.4.0-0.dev-25-g17db8bd-arm64
v3.4.0-0.dev-25-g17db8bd-ppc64le
Something that jumps out there is that the last tag is included in the new list, which isn't valid from the OCI spec. Instead, the results should look like what Hub does:
$ regctl tag ls calico/node --limit 10
06d8348
0b3286c-e9613934-1eb2608
2606b97-e0ce0bc-7a66b57
2606b97-e0ce0bca-7a66b57
383a737
43b069c
4d0d1ec
4fac26c-0ff3c42a-f442384
53afe8a
542c040
$ regctl tag ls calico/node --limit 10 --last 542c040
684ef2b
6889069
69c3089
6ce4f0a
714dda5-36dc8f6f-aa95469
714dda5-48a4a83d-aa95469
714dda5-6af11396-aa95469
765dc25
91d54c3
9512289
I've also noticed when I increase the limit, I'll start seeing entries returned from even further before the "last" entry that I requested, and it's using a previous "last" parameter for these offsets. Most likely it's some weird caching happening, which is documented in this Jira issue. For right now, it appears that Quay is not following the OCI distribution-spec which makes this difficult to test and use, and will need to be fixed by Quay.
I am doing some work with docker container management, and need to get docker container status.
My current approach is using ssh client by execute shell cmd to grab.
For example i can get container stats by execute cmd:
docker stats --no-stream --format '{"container":"{{ .Name }}","memory":{"raw":"{{ .MemUsage }}","percent":"{{ .MemPerc }}"},"cpu":"{{ .CPUPerc }}","networkIO":"{{.NetIO}}","BlockIO":"{{.BlockIO}}"}'
output:
{"container":"postgresql","memory":{"raw":"255.4MiB / 31.21GiB","percent":"0.80%"},"cpu":"0.00%","networkIO":"1.03GB / 476MB,"BlockIO":"545MB / 7.67GB"}
{"container":"pgadmin","memory":{"raw":"146.1MiB / 31.21GiB","percent":"0.46%"},"cpu":"0.03%","networkIO":"26.2kB / 0B,"BlockIO":"200MB / 8.19kB"}
{"container":"pis_middle_layer_flask","memory":{"raw":"849.9MiB / 31.21GiB","percent":"2.66%"},"cpu":"13.48%","networkIO":"26.4kB / 0B,"BlockIO":"65.9MB / 0B"}
So how can i get similar text with docker system df -v?
Cause i want to get each container size and their volume size.
I did with same cmd:
docker system df -v --format '{"container":"{{ .Name }}","memory":{"raw":"{{ .MemUsage }}","percent":"{{ .MemPerc }}"},"cpu":"{{ .CPUPerc }}","networkIO":"{{.NetIO}}","BlockIO":"{{.BlockIO}}"}'
but occurred with error:
{"container":"template: :1:17: executing "" at <.Name>: can't evaluate field Name in type *formatter.diskUsageContext
I know i got wrong go template keywords, but really can't find anything doc about it.
Al right...just got it.
docker system df -v --format "{{ json . }}"
this cmd will return as json so i can parse it with json.loads
According to the documentation at: https://docs.docker.com/engine/reference/commandline/cli/#customize-the-default-output-format-for-commands
I want to customize the docker ps output so that it shows the IP of the containers in the table results.
What I've tried so far is:
$ cat ~/.docker/config.json
{
"psFormat": "table {{.ID}}\\t{{.Image}}\\t{{.IPAddress}}\\t{{.Ports}}\\t{{.Names}}"
}
but then it raises this error:
$ docker ps
Template parsing error: template: :1:33: executing "" at <.IPAddress>:
can't evaluate field IPAddress in type *formatter.ContainerContext
I also know that docker inspect accept a --format argument having kind of the same structure:
$ docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}} {{.Name}}' my-project_app_1
172.19.0.2 /my-project_app_1
So I also naively tried to copy/paste that format structure into the docker config.json file:
$ cat ~/.docker/config.json
{
"psFormat": "table {{.ID}}\\t{{.Image}}\\t{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}\\t{{.Ports}}\\t{{.Names}}"
}
but then this error shows up:
Template parsing error: template: :1:55: executing "" at <.NetworkSettings.Networks>:
can't evaluate field NetworkSettings in type *formatter.ContainerContext
Question
How would you get the IP of the container in the table formatted output of a custom docker ps command?
System info:
Ubuntu: 18.04.6 LTS
Kernel: 5.4.0-94-generic x86_64 GNU/Linux
Docker: Docker version 20.10.12, build e91ed57
I created an docker image that has few labels, here is my Dockerfile section on LABELS:
grep LABEL Dockerfile
LABEL "css1"="/var/www/css1"
LABEL "css2"="/var/www/css2"
LABEL "img"="/var/www/img"
LABEL "js"="/var/www/js"
Then:
docker image inspect --format='{{.Config.Labels}}' labels-test
map[css1:/var/www/css1 css2:/var/www/css2 img:/var/www/img js:/var/www/js]
I need to get for example all labels starting with css. This is as far as i was able to figure:
docker image inspect --format='{{range $k,$v:=.Config.Labels}}{{$k}}:{{$v}} {{end}}' labels-test
css1:/var/www/css1 css2:/var/www/css2 img:/var/www/img js:/var/www/js
Desired output would be:
css1:/var/www/css1 css2:/var/www/css2
The Go template functions are available in golang docco
eq can test if arg1 == arg2.
printf "%.3s" $k will give you the first 3 chars of a string.
docker image inspect \
--format='{{ range $k,$v:=.Config.Labels }}{{ if eq (printf "%.3s" $k) "css" }}{{ $k }}:{{ $v }} {{end}}{{end}}' \
IMAGE
You might want to look at the querying the Docker API images endpoint /images/IMAGE/json directly or processing the JSON output somewhere if you need to do any more advanced processing:
docker image inspect \
--format='{{json .Config.Labels}}' \
IMAGE
You can do something like
docker inspect --format='{{index (index (.Config.Labels)).css1 }}' labels-test
which shows for me
/var/www/css1
and also
docker inspect --format='{{index (index (.Config.Labels)).css2 }}' labels-test
which shows for me
/var/www/css2
See my previous answer on that subject
How to get ENV variable when doing Docker Inspect
Edit
The following gives exactly what you ask for
docker inspect --format='{{index (index (.Config.Labels)).css1 }} {{index (index (.Config.Labels)).css2 }} labels-test
as i get
/var/www/css1 /var/www/css2
How to escape double curly braces in Ansible 1.9.2?
For instance, how can I escape double curly braces in the following shell command?
- name: Test
shell: "docker inspect --format '{{ .NetworkSettings.IPAddress }}' instance1"
Whenever you have problems with conflicting characters in Ansible, a rule of thumb is to output them as a string in a Jinja expression.
So instead of {{ you would use {{ '{{' }}:
- debug: msg="docker inspect --format '{{ '{{' }} .NetworkSettings.IPAddress {{ '}}' }}' instance1"
Topic "Escaping" in the Jinja2 docs.
This:
- name: Test
shell: "docker inspect --format {% raw %}'{{ .NetworkSettings.IPAddress }}' {% endraw %} instance1"
Should work
Another way to do is using backslashes like \{\{ .NetworkSettings.IPAddress \}\}
Hope it helps
Tried on with ansible 2.1.1.0
{%raw%}...{%endraw%} block seems the clear way
- name: list container images and name date on the server
shell: docker ps --format {%raw%}"{{.Image}} {{.Names}}"{%endraw%}
Only need to escape leading '{{'
tasks:
- name: list container images and names
shell: docker ps --format "{{'{{'}}.Image}} {{'{{'}}.Names}}"
No harm to escap the tailing '}}', except more difficult to read.
tasks:
- name: list container images and names
shell: docker ps --format "{{'{{'}}.Image{{'}}'}} {{'{{'}}.Names{{'}}'}}"
Backslash '\' seems do not work
New in Ansible 2.0 is the ability to declare a value as unsafe with the !unsafe tag.
In your example you could do:
- name: Test
shell: !unsafe "docker inspect --format '{{ .NetworkSettings.IPAddress }}' instance1"
See the docs for details.
I have a similar issue: i need to post a JSON doc made from a jinja2 template containing some go templates variables (yes, i know :-P), such as
"NAME_TEMPLATE": %{{service_name}}.%{{stack_name}}.%{{environment_name}}
Trying to fence this part of the template between
{% raw %} ... {% endraw %}
didn't work because there is some sort of magic in ansible which will run the template and variable substition twice (i'm not sure about that, but it definitively looks like this)
You end up with "undefined variable service_name" when trying to use the template...
So i ended up using a combination of !unsafe and {% raw %} ... {% endraw %} to define a fact that's later used in the template.
- set_fact:
__rancher_init_root_domain: "{{ rancher_root_domain }}"
#!unsafe: try to trick ansible into not doing substitutions in that string, then use %raw% so the value won't substituted another time
__rancher_init_name_template: !unsafe "{%raw%}%{{service_name}}.%{{stack_name}}.%{{environment_name}}{%endraw%}"
- name: build a template for a project
set_fact:
__rancher_init_template_doc: "{{ lookup('template', 'templates/project_template.json.j2') }}"
the template contains this:
"ROOT_DOMAIN":"{{__rancher_init_root_domain}}",
"ROUTE53_ZONE_ID":"",
"NAME_TEMPLATE":"{{__rancher_init_name_template }}",
"HEALTH_CHECK":"10000",
and the output is ok:
"NAME_TEMPLATE": "%{{service_name}}.%{{stack_name}}.%{{environment_name}}",
Here's a shorter alternative to udondan's answer; surround the whole string with double brackets:
shell: "docker inspect --format {{ '{{ .NetworkSettings.IPAddress }}' }} instance1"
The solution by using raw has been already mentioned but the command in the answer before unfortunately didn't work for me.
Without ansible:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker_instance_name
With ansible:
- name: Get ip of db container
shell: "{% raw %}docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker_instance_name{% endraw %}"
register: db_ip_addr
- debug:
var: db_ip_addr.stdout
I managed to work around my issue using a small script:
#!/usr/bin/env bash
docker inspect --format '{{ .NetworkSettings.IPAddress }}' "$1"
And the following Ansible play
- copy:
src: files/get_docker_ip.sh
dest: /usr/local/bin/get_docker_ip.sh
owner: root
group: root
mode: 0770
- shell: "/usr/local/bin/get_docker_ip.sh {{ SWIFT_ACCOUNT_HOSTNAME }}"
register: swift_account_info
Nevertheless, it's very surprising that Ansible doesn't allow escaping double curly braces!
I was unable to get #Ben's answer to work (shell: !unsafe ...)
What follows here is a complete (and working!) answer to the OP's question, updated for Ansible >2.0
---
# file: play.yml
- hosts: localhost
connection: local
gather_facts: no
vars:
# regarding !unsafe, please see:
# https://docs.ansible.com/ansible/latest/user_guide/playbooks_advanced_syntax.html
#
- NetworkSettings_IPAddress: !unsafe "{{.NetworkSettings.IPAddress}}"
tasks:
- shell: "docker inspect --format '{{NetworkSettings_IPAddress}}' instance1"
register: out
- debug: var="{{item}}"
with_items:
- out.cmd
- out.stdout
outputs: ([WARNINGS] removed)
# ansible-playbook play.yml
PLAY [localhost] ***************************************************************
TASK [shell] *******************************************************************
changed: [localhost]
TASK [debug] *******************************************************************
ok: [localhost] => (item=out.cmd) => {
"item": "out.cmd",
"out.cmd": "docker inspect --format '{{.NetworkSettings.IPAddress}}' instance1"
}
ok: [localhost] => (item=out.stdout) => {
"item": "out.stdout",
"out.stdout": "172.17.0.2"
}
PLAY RECAP *********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0
# ansible --version | head -1
ansible 2.6.1
Here is a mostly clean and Ansible native workaround not depending on docker --inspect with curly braces. We assume we have just referenced one container with the Ansible docker module before:
- name: query IP of client container
shell: "docker exec {{ docker_containers[0].Id }} hostname -I"
register: _container_query
- name: get IP of query result
set_fact:
_container_ip: "{{ _container_query.stdout | regex_replace('\\s','') }}"
You now have the IP of the Docker container in the Variable _container_ip. I also published this workaround on my article The Marriage of Ansible with Docker.
[Update 2015-11-03] Removed whitespaces of the stdout of the container query.
[Update 2015-11-04] BTW, there were two pull requests in the official Ansible repository, that would made this workaround needless by recovering the facts returned by the Docker module. So you could acces the IP of a docker container via docker_containers[0].NetworkSettings.IPAddress. So please vote for those pull requests:
fixed broken facts #1457
docker module: fix regressions introduced by f38186c and 80aca4b #2093