Can I alias a subcommand? (shortening the output of `docker ps`) - docker

The docker command has a ps sub-command that emits very long lines:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6e8ec8a16da4 waisbrot/wait:latest "/wait" 4 minutes ago Exited (0) 4 minutes ago wait-for-janus-test
9dbf0739561f whoop/downsampler:master "./run.bash" 4 minutes ago Up 4 minutes 0.0.0.0:32855->4369/tcp, 0.0.0.0:32854->9100/tcp, 0.0.0.0:32853->9101/tcp, 0.0.0.0:32852->9102/tcp, 0.0.0.0:32851->9103/tcp, 0.0.0.0:32850->9104/tcp, 0.0.0.0:32849->9105/tcp, 0.0.0.0:32848->9106/tcp, 0.0.0.0:32847->9107/tcp, 0.0.0.0:32846->9108/tcp, 0.0.0.0:32845->9109/tcp, 0.0.0.0:32844->9110/tcp metrics-downsampler-test
6cf56623bb48 whoop/janus:master "./start.bash" 4 minutes ago Up 4 minutes 0.0.0.0:32843->80/tcp janus-test
882b50303d54 whoop/recalculator:master "./run.bash" 4 minutes ago Exited (1) 4 minutes ago internum-test
It can be instructed to output only specific columns:
docker ps --format "table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}"
I'd like to be able to say docker ps and get the --format "table..." argument added on for me. Is there a nice way to do this?
I know I could say
alias dp='docker ps --format ...'
but I'd prefer to keep the sub-command.
I'm using zsh as my shell.

You can wrap docker in a function that checks for the specific subcommand and passes everything else through. (The below will actually work with not just zsh, but any POSIX-compliant shell -- a category to which zsh doesn't quite belong).
docker() {
case $1 in
ps)
shift
command docker ps --format 'table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}' "$#"
;;
*)
command docker "$#";;
esac
}
If you wanted a more generic wrapper function (that doesn't need to know about your specific desired ps logic), that could be done as follows (note that this version is not compatible with baseline POSIX sh due to its use of local; however, this is an extension implemented even by ash and its derivatives):
docker() {
local cmd=$1; shift
if command -v "docker_$cmd" >/dev/null 2>/dev/null; then
"docker_$cmd" "$#"
else
command docker "$cmd" "$#"
fi
}
...after which any subcommand can have its own functions defined, without the wrapper needing to be modified to know about them (you could also create a script in the PATH named docker_ps, or provide the command in any other manner you choose):
docker_ps() {
command docker ps --format 'table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}' "$#"
}

Using Docker Config
Since this is fundamentally a docker questions, not a bash question, you don't even need an alias. Docker CLI allows you to customize these commands in your own config file! From this great tip from Container 42:
Create or find your docker config file (if you've ever used docker login it should already be created.
~/.docker/config.json
Then add the default formatting for docker to use every time it runs the ps command as a top level property in the config:
{
"psFormat": "table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}",
}
Then just run docker ps like normal:
PS Format
Docker uses go templates and has a list of the valid placeholders:
Command
Description
.ID
Container ID
.Image
Image ID
.Command
Quoted command
.CreatedAt
Time when the container was created.
.RunningFor
Elapsed time since the container was started.
.Ports
Exposed ports.
.Status
Container status.
.Size
Container disk size.
.Names
Container names.
.Labels
All labels assigned to the container.
.Label
Value of a specific label for this container.
.Mounts
Names of the volumes mounted in this container.
.Networks
Names of the networks attached to this container.
Alternative Solutions / Threads
Github Issues
Default "docker ps" output is too wide
docker ps output is so long it's unreadable
Third Party Commands
ctop - Top-like interface for container metrics
docker-pretty-ps - beautiful, colored, long output log
dockerps - A better docker ps

You can alias subcommands. With aliasing, you still get the nice zsh completions as if you were typing the full command. That's why I prefer them over functions.
The equivalent of your alias is:
alias dp='docker ps --format "table {{.Image}}\t{{.Names}}\t{{.Ports}}'\t{{.Status}}"
But the full commands seem to now be recommended, and ls has replaced ps, which makes your alias now:
alias dp='docker container ls --format "table {{.Image}}\t{{.Names}}\t{{.Ports}}'\t{{.Status}}"
It's nice to have docker aliases for everything. For this, I've been working on a set of comprehensive aliases, which would have your alias as something like:
alias ddcls='docker container ls --format "table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}"

In my case, I needed to disable only docker login command (some folks used that command on our CI-runner breaking a generic config file for docker).
So, I added to my .bashrc:
_docker() {
if [ "$1" = "login" ]; then
echo "login is disabled, to login please update a config file manually!"
return
fi
/usr/bin/docker "$#"
}
alias docker="_docker"

Related

How to delete specific running docker containers in batch

I need to run more than 70 docker containers at once. Later, these containers need to be stopped.
At the moment I can docker stop all of them with the shell command docker stop $(docker ps -f since=<last docker before>). It works OK, but if there are any containers started after mine, I have a problem as the above code will stop them too.
Is there any way I can close all of running containers with some kind of specific search?
I know there is an docker ps -f label=<some label>, but I just haven't figured out on how to use it yet.
If you're launching many containers at the same time, launch them all with
docker run --label=anyname other-docker-args-of-yours image:tag
And when you want to delete all your containers just do
docker stop $(docker ps -f label=anyname | awk 'NR>1 {print$1}')
where anyname is the label name you provide during the docker run command and
awk 'NR>1 {print$1}' ignores the column header CONTAINER_ID and just prints the values alone.
Edit-1:
I later realized that you can achieve the list of Container_ID without awk as well. I'd consider using the below line.
docker stop `docker ps -qaf label=anyname`
If you want to remove all stoppped containers also, then include a within the options, like instead of -qf use -qaf.
-q to print container IDs alone.
-a for all containers including stopped.

How can I see which user launched a Docker container?

I can view the list of running containers with docker ps or equivalently docker container ls (added in Docker 1.13). However, it doesn't display the user who launched each Docker container. How can I see which user launched a Docker container? Ideally I would prefer to have the list of running containers along with the user for launched each of them.
You can try this;
docker inspect $(docker ps -q) --format '{{.Config.User}} {{.Name}}'
Edit: Container name added to output
There's no built in way to do this.
You can check the user that the application inside the container is configured to run as by inspecting the container for the .Config.User field, and if it's blank the default is uid 0 (root). But this doesn't tell you who ran the docker command that started the container. User bob with access to docker can run a container as any uid (this is the docker run -u 1234 some-image option to run as uid 1234). Most images that haven't been hardened will default to running as root no matter the user that starts the container.
To understand why, realize that docker is a client/server app, and the server can receive connections in different ways. By default, this server is running as root, and users can submit requests with any configuration. These requests may be over a unix socket, you could sudo to root to connect to that socket, you could expose the API to the network (not recommended), or you may have another layer of tooling on top of docker (e.g. Kubernetes with the docker-shim). The big issue in that list is the difference between the network requests vs a unix socket, because network requests don't tell you who's running on the remote host, and if it did, you'd be trusting that remote client to provide accurate information. And since the API is documented, anyone with a curl command could submit a request claiming to be a different user.
In short, every user with access to the docker API is an anonymized root user on your host.
The closest you can get is to either place something in front of docker that authenticates users and populates something like a label. Or trust users to populate that label and be honest (because there's nothing in docker validating these settings).
$ docker run -l "user=$(id -u)" -d --rm --name test-label busybox tail -f /dev/null
...
$ docker container inspect test-label --format '{{ .Config.Labels.user }}'
1000
Beyond that, if you have a deployed container, sometimes you can infer the user by looking through the configuration and finding volume mappings back to that user's home directory. That gives you a strong likelihood, but again, not a guarantee since any user can set any volume.
I found a solution. It is not perfect, but it works for me.
I start all my containers with an environment variable ($CONTAINER_OWNER in my case) which includes the user. Then, I can list the containers with the environment variable.
Start container with environment variable
docker run -e CONTAINER_OWNER=$(whoami) MY_CONTAINER
Start docker compose with environment variable
echo "CONTAINER_OWNER=$(whoami)" > deployment.env # Create env file
docker-compose --env-file deployment.env up
List containers with the environment variable
for container_id in $(docker container ls -q); do
echo $container_id $(docker exec $container_id bash -c 'echo "$CONTAINER_OWNER"')
done
As far as I know, docker inspect will show only the configuration that
the container started with.
Because of the fact that commands like entrypoint (or any init script) might change the user, those changes will not be reflected on the docker inspect output.
In order to work around this, you can to overwrite the default entrypoint set by the image with --entrypoint="" and specify a command like whoami or id after it.
You asked specifically to see all the containers running and the launched user, so this solution is only partial and gives you the user in case it doesn't appear with the docker inspect command:
docker run --entrypoint "" <image-name> whoami
Maybe somebody will proceed from this point to a full solution (:
Read more about entrypoint "" in here.
If you are used to ps command, running ps on the Docker host and grep with parts of the process your process is running. For example, if you have a Tomcat container running, you may run the following command to get details on which user would have started the container.
ps -u | grep tomcat
This is possible because containers are nothing but processes managed by docker. However, this will only work on single host. Docker provides alternatives to get container details as mentioned in other answer.
this command will print the uid and gid
docker exec <CONTAINER_ID> id
ps -aux | less
Find the process's name (the one running inside the container) in the list (last column) and you will see the user ran it in the first column

Is there a difference between "docker ps" and "docker container ls"?

The documentation of docker ps and docker container ls both says "List containers", but does not mention the other command. Is there a difference between those two commands?
The output looks exactly the same:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bbe3d7158eaa flaskmysqldockerized_web "python app.py" 5 hours ago Up 18 seconds 0.0.0.0:8082->5000/tcp flaskmysqldockerized_web_1
4f7d3f0763ad mysql "docker-entrypoint..." 6 hours ago Up 18 seconds 0.0.0.0:3307->3306/tcp flaskmysqldockerized_db_1
There is no difference between docker ps and docker container ls. The new command structure (docker container <subcommand>) was added in Docker 1.13 to provider a more structured user experience when using the command line.
To my knowledge, there has not yet been any official announcement to drop support for the old-style commands (like docker ps and others), although it might be reasonable to assume this might happen at some point in the future.
This is described in a blog post accompanying the release of Docker 1.13:
Docker has grown many features over the past couple years and the Docker CLI now has a lot of commands (40 at the time of writing). Some, like build or run are used a lot, some are more obscure, like pause or history. The many top-level commands clutters help pages and makes tab-completion harder.
In Docker 1.13, we regrouped every command to sit under the logical object it’s interacting with. For example list and startof containers are now subcommands of docker container and history is a subcommand of docker image.
docker container list
docker container start
docker image history
These changes let us clean up the Docker CLI syntax, improve help text and make Docker simpler to use. The old command syntax is still supported, but we encourage everybody to adopt the new syntax.
docker ps is shorthand that stands for "docker process status", whilst docker container ls is shorthand for the more verbose docker container list.
As the accepted answer explains, there is no difference in how they work, and docker container ls is the 'newer' command, so you should probably prefer it.
Both commands actually only show running containers by default, which makes the first one (docker ps) a little more confusing as that command on its own isn't really showing 'process status'. To see the status of all containers, add the -a option for 'all' (or use --all), e.g.
docker container ls -a
older
docker ps -a or docker container ps -a

Docker: How to clear the logs properly for a Docker container?

I use docker logs [container-name] to see the logs of a specific container.
Is there an elegant way to clear these logs?
First the bad answer. From this question there's a one-liner that you can run:
echo "" > $(docker inspect --format='{{.LogPath}}' <container_name_or_id>)
instead of echo, there's the simpler:
: > $(docker inspect --format='{{.LogPath}}' <container_name_or_id>)
or there's the truncate command:
truncate -s 0 $(docker inspect --format='{{.LogPath}}' <container_name_or_id>)
I'm not a big fan of either of those since they modify Docker's files directly. The external log deletion could happen while docker is writing json formatted data to the file, resulting in a partial line, and breaking the ability to read any logs from the docker logs cli. For an example of that happening, see this comment on duketwo's answer:
after emptying the logfile, I get this error: error from daemon in stream: Error grabbing logs: invalid character '\x00' looking for beginning of value
Instead, you can have Docker automatically rotate the logs for you. This is done with additional flags to dockerd if you are using the default JSON logging driver:
dockerd ... --log-opt max-size=10m --log-opt max-file=3
You can also set this as part of your daemon.json file instead of modifying your startup scripts:
{
"log-driver": "json-file",
"log-opts": {"max-size": "10m", "max-file": "3"}
}
These options need to be configured with root access. Make sure to run a systemctl reload docker after changing this file to have the settings applied. This setting will then be the default for any newly created containers. Note, existing containers need to be deleted and recreated to receive the new log limits.
Similar log options can be passed to individual containers to override these defaults, allowing you to save more or fewer logs on individual containers. From docker run this looks like:
docker run --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 ...
or in a compose file:
version: '3.7'
services:
app:
image: ...
logging:
options:
max-size: "10m"
max-file: "3"
For additional space savings, you can switch from the json log driver to the "local" log driver. It takes the same max-size and max-file options, but instead of storing in json it uses a binary syntax that is faster and smaller. This allows you to store more logs in the same sized file. The daemon.json entry for that looks like:
{
"log-driver": "local",
"log-opts": {"max-size": "10m", "max-file": "3"}
}
The downside of the local driver is external log parsers/forwarders that depended on direct access to the json logs will no longer work. So if you use a tool like filebeat to send to Elastic, or Splunk's universal forwarder, I'd avoid the "local" driver.
I've got a bit more on this in my Tips and Tricks presentation.
Use:
truncate -s 0 /var/lib/docker/containers/**/*-json.log
You may need sudo
sudo sh -c "truncate -s 0 /var/lib/docker/containers/**/*-json.log"
ref. Jeff S. Docker: How to clear the logs properly for a Docker container?
Reference: Truncating a file while it's being used (Linux)
On Docker for Windows and Mac, and probably others too, it is possible to use the tail option. For example:
docker logs -f --tail 100
This way, only the last 100 lines are shown, and you don't have first to scroll through 1M lines...
(And thus, deleting the log is probably unnecessary)
sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"
You can set up logrotate to clear the logs periodically.
Example file in /etc/logrotate.d/docker-logs
/var/lib/docker/containers/*/*.log {
rotate 7
daily
compress
size=50M
missingok
delaycompress
copytruncate
}
You can also supply the log-opts parameters on the docker run command line, like this:
docker run --log-opt max-size=10m --log-opt max-file=5 my-app:latest
or in a docker-compose.yml like this
my-app:
image: my-app:latest
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
Credits: https://medium.com/#Quigley_Ja/rotating-docker-logs-keeping-your-overlay-folder-small-40cfa2155412 (James Quigley)
Docker4Mac, a 2018 solution:
LOGPATH=$(docker inspect --format='{{.LogPath}}' <container_name_or_id>)
docker run -it --rm --privileged --pid=host alpine:latest nsenter -t 1 -m -u -n -i -- truncate -s0 $LOGPATH
The first line gets the log file path, similar to the accepted answer.
The second line uses nsenter that allows you to run commands in the xhyve VM that servers as the host for all the docker containers under Docker4Mac. The command we run is the familiar truncate -s0 $LOGPATH from non-Mac answers.
If you're using docker-compose, the first line becomes:
local LOGPATH=$(docker inspect --format='{{.LogPath}}' $(docker-compose ps -q <service>))
and <service> is the service name from your docker-compose.yml file.
Thanks to https://github.com/justincormack/nsenter1 for the nsenter trick.
You can't do this directly through a Docker command.
You can either limit the log's size, or use a script to delete logs related to a container. You can find scripts examples here (read from the bottom): Feature: Ability to clear log history #1083
Check out the logging section of the docker-compose file reference, where you can specify options (such as log rotation and log size limit) for some logging drivers.
Here is a cross platform solution to clearing docker container logs:
docker run --rm -v /var/lib/docker:/var/lib/docker alpine sh -c "echo '' > $(docker inspect --format='{{.LogPath}}' CONTAINER_NAME)"
Paste this into your terminal and change CONTAINER_NAME to desired container name or id.
As a root user, try to run the following:
> /var/lib/docker/containers/*/*-json.log
or
cat /dev/null > /var/lib/docker/containers/*/*-json.log
or
echo "" > /var/lib/docker/containers/*/*-json.log
On my Ubuntu servers even as sudo I would get Cannot open ‘/var/lib/docker/containers/*/*-json.log’ for writing: No such file or directory
But combing the docker inspect and truncate answers worked :
sudo truncate -s 0 `docker inspect --format='{{.LogPath}}' <container>`
I do prefer this one (from solutions above):
truncate -s 0 /var/lib/docker/containers/*/*-json.log
However I'm running several systems (Ubuntu 18.x Bionic for example), where this path does not work as expected. Docker is installed through Snap, so the path to containers is more like:
truncate -s 0 /var/snap/docker/common/var-lib-docker/containers/*/*-json.log
This will delete all logfiles for all containers:
sudo find /var/lib/docker/containers/ -type f -name "*.log" -delete
Thanks to answer by #BMitch, I've just wrote a shell script to clean logs of all the containers:
#!/bin/bash
ids=$(docker ps -a --format='{{.ID}}')
for id in $ids
do
echo $(docker ps -a --format='{{.ID}} ### {{.Names}} ### {{.Image}}' | fgrep $id)
truncate -s 0 $(docker inspect --format='{{.LogPath}}' $id)
ls -llh $(docker inspect --format='{{.LogPath}}' $id)
done
Not sure if this is helpful for you, but removing the container always helps.
So, if you use docker-compose for your setup, you can simply use docker-compose down && docker-compose up -d instead of docker-compose restart. With a proper setup (make sure to use volume mounts for persistent data), you don't lose any data this way.
Sure, this is more than the OP requested. But there are various situations where the other answers cannot help (if using a remote docker server or working on a Windows machine, accessing the underlying filesystem is proprietary and difficult)
Linux/Ubuntu:
If you have several containers and you want to remove just one log but not others.
(If you have issues like "Permission denied" do first sudo su.)
List all containers: docker ps -a
Look for the container you desire and copy the CONTAINER ID. Example: E1X2A3M4P5L6.
Containers folders and real names are longer than E1X2A3M4P5L6 but first 12 characters are those resulted in docker ps -a.
Remove just that log:
> /var/lib/docker/containers/E1X2A3M4P5L6*/E1X2A3M4P5L6*-json.log (Replace E1X2A3M4P5L6 for your result !! )
As you can see, inside /containers are the containers, and logs has the same name but with -json.log at the end. You just need to know that first 12 characters, because * means "anything".
Docker for Mac users, here is the solution:
Find log file path by:
$ docker inspect | grep log
SSH into the docker machine( suppose the name is default, if not, run docker-machine ls to find out):
$ docker-machine ssh default
Change to root user(reference):
$ sudo -i
Delete the log file content:
$ echo "" > log_file_path_from_step1
I needed something I could run as one command, instead of having to write docker ps and copying over each Container ID and running the command multiple times. I've adapted BMitch's answer and thought I'd share in case someone else may find this useful.
Mixing xargs seems to pull off what I need here:
docker ps --format='{{.ID}}' | \
xargs -I {} sh -c 'echo > $(docker inspect --format="{{.LogPath}}" {})'
This grabs each Container ID listed by docker ps (will erase your logs for any container on that list!), pipes it into xargs and then echoes a blank string to replace the log path of the container.
To remove/clear docker container logs we can use below command
$(docker inspect container_id|grep "LogPath"|cut -d """ -f4)
or
$(docker inspect container_name|grep "LogPath"|cut -d """ -f4)
If you need to store a backup of the log files before deleting them, I have created a script that performs the following actions (you have to run it with sudo) for a specified container:
Creates a folder to store compressed log files as backup.
Looks for the running container's id (specified by the container's name).
Copy the container's log file to a new location (folder in step 1) using a random name.
Compress the previous log file (to save space).
Truncates the container's log file by certain size that you can define.
Notes:
It uses the shuf command. Make sure your linux distribution has it or change it to another bash-supported random generator.
Before use, change the variable CONTAINER_NAME to match your running container; it can be a partial name (doesn't have to be the exact matching name).
By default it truncates the log file to 10M (10 megabytes), but you can change this size by modifying the variable SIZE_TO_TRUNCATE.
It creates a folder in the path: /opt/your-container-name/logs, if you want to store the compressed logs somewhere else, just change the variable LOG_FOLDER.
Run some tests before running it in production.
#!/bin/bash
set -ex
############################# Main Variables Definition:
CONTAINER_NAME="your-container-name"
SIZE_TO_TRUNCATE="10M"
############################# Other Variables Definition:
CURRENT_DATE=$(date "+%d-%b-%Y-%H-%M-%S")
RANDOM_VALUE=$(shuf -i 1-1000000 -n 1)
LOG_FOLDER="/opt/${CONTAINER_NAME}/logs"
CN=$(docker ps --no-trunc -f name=${CONTAINER_NAME} | awk '{print $1}' | tail -n +2)
LOG_DOCKER_FILE="$(docker inspect --format='{{.LogPath}}' ${CN})"
LOG_FILE_NAME="${CURRENT_DATE}-${RANDOM_VALUE}"
############################# Procedure:
mkdir -p "${LOG_FOLDER}"
cp ${LOG_DOCKER_FILE} "${LOG_FOLDER}/${LOG_FILE_NAME}.log"
cd ${LOG_FOLDER}
tar -cvzf "${LOG_FILE_NAME}.tar.gz" "${LOG_FILE_NAME}.log"
rm -rf "${LOG_FILE_NAME}.log"
truncate -s ${SIZE_TO_TRUNCATE} ${LOG_DOCKER_FILE}
You can create a cronjob to run the previous script every month. First run:
sudo crontab -e
Type a in your keyboard to enter edit mode. Then add the following line:
0 0 1 * * /your-script-path/script.sh
Hit the escape key to exit Edit mode. Save the file by typing :wq and hitting enter. Make sure the script.sh file has execution permissions.
On computers with docker desktop we use:
truncate -s 0 //wsl.localhost/docker-desktop-data/data/docker/containers/*/*-json.log
For linux distributions you can use this it works for me with this path:
truncate -s 0 /var/lib/docker/containers/*/*-json.log
docker system prune
run this command in command prompt

How to get container id of running container programmatically (on Docker)?

I have an app in a docker setup. I would like to run a script on the host that would run some commands in an existing (running container).
If I know the container id, say ... it's 50250e572090 ... then I can run the script like this
For example ...
#!/usr/bin/env bash
docker exec 50250e572090 example_command_1_here
docker exec 50250e572090 example_command_2_here
docker exec 50250e572090 example_command_3_here
docker exec 50250e572090 example_command_4_here
It's working great! ... but the thing here is that I only know the image name ... not the container id. To find the container id ... I use docker ps ... where I get something like this ...
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
50250e572090 aws_beanstalk/staging-app:latest "/sbin/my_init" 29 hours ago Up 29 hours 80/tcp, 443/tcp drunk_bardeen
It's output isn't something that I can use (pipe through). Which command can I run to get the container id as the output which can then be piped into the script? Or now that it's clear what I'm trying to achieve ... is there a better way?
Ps: My context is that I'm on elastic beanstalk ... but I don't see how this changes anything. Might as well be on the local host ... the problem is the same.
I was able to achieve this using the -q flag. Like so ...
#!/usr/bin/env bash
docker exec `docker ps -q` example_command_1_here
docker exec `docker ps -q` example_command_2_here
docker exec `docker ps -q` example_command_3_here
docker exec `docker ps -q` example_command_4_here
What you're requesting is not that easy. Multiple containers can use the same image.
You can use docker ps with a filter to only see containers derived from a specific image:
$ docker ps -q --filter "ancestor=aws_beanstalk/staging-app:latest"
Please note that this will return all running containers using the aws_beanstalk/staging-app:latest image which might be more than one.
You can run docker inspect command and get the Id of the container;
viswesn#viswesn-PC1:~$ docker inspect My_First_Docker | grep Id | awk '{print $2}'
"e3824f0121f24dded9792f133344a2d68b46ea13065481c30caf35d0ac6be40e",
I know this question is old, but I wanted a better answer than was given here, and I figured it out:
docker ps -q --no-trunc --format="{{.ID}}" --filter "ancestor=image/repo/and:tag"
You can leave off :tag if you want, or you can filter on something else entirely. The output will be the full, un-truncated ID of each matching container. No column headers or anything else extraneous.
If you only need the short version (first twelve hex digits) of the ID, leave off --no-trunc.

Resources