When starting a container, if you do not specify --name
, the container name will be randomly assigned. It is great_wescoff
in the following.
$ docker run alpine:latest
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0772fae09ab1 alpine:latest "/bin/sh" 16 seconds ago Exited (0) 15 seconds ago great_wescoff
Suddenly, I was wondering how this name was generated.
Since it is open source, you can find the answer by looking at it, but I will try to find out for myself and finally match the answers.
The way to find out is to run a lot of docker run
s, extract (almost) all the names patterns, and look at them to find the rules.
$ docker run -d alpine:latest
Run some image. The image to be executed can be anything, but I chose the one that is as lightweight as possible.
The -d
option is a command that runs the container in the background.
However, this time it is used to output the container ID, not for that purpose.
$ docker ps -a -f "id=$cid" --format "{{.Names}}"
Extract the container name using the container ID (cid) output earlier.
Display all containers (including those that do not appear during execution) with the -a
option,
Filter by container ID with the -f
option and
Customize the display format with --format
.
$ docker rm $cid
If the container name can be extracted, the rest is useless, so delete it.
Create a shell script by combining the above docker commands.
names
is the file that contains the list of container names.
Get 1000 container names, and if all 1000 are duplicated with the accumulated container names, it will end. Until then, it loops infinitely.
total=0
while true; do
for i in `seq 1000`; do
cid=$(docker run -d alpine:latest)
docker ps -a -f "id=$cid" --format "{{.Names}}" >> names
docker rm $cid > /dev/null
done
sort -u names -o names
after_wc=$(cat names | wc -l | tr -d ' ')
if [ "$total" = "$after_wc" ]; then
exit
else
echo "continue (find new name: $(($after_wc-$total)))"
total=$after_wc
fi
done
The process wasn't finished, so I decided to speed it up a bit. At this point, the number of new names has dropped to about 500 for each epoch, so it seems that it will level off somewhere.
After all, the part that executes the docker command is the bottleneck, so I decided to execute it in parallel to some extent.
total=0
get_name() {
for i in `seq 100`; do
cid=$(docker run -d alpine:latest)
docker ps -a -f "id=$cid" --format "{{.Names}}" >> names
docker rm $cid > /dev/null
done
}
export -f get_name
while true; do
seq 10 | xargs -I ZZ -P 10 sh -c get_name
sort -u names -o names
after_wc=$(cat names | wc -l | tr -d ' ')
if [ "$total" = "$after_wc" ]; then
exit
else
echo "continue (find new name: $(($after_wc-$total)))"
total=$after_wc
fi
done
Make the part to get the name a function and execute it in 10 parallels. If the number of parallels is large, the processing can be speeded up, but due to PC specifications, the following errors frequently occur, and in the worst case docker does not work.
Error response from daemon: You cannot remove a running container 54161ca2bea3d750a3e873a329a760af990dfcc115cb13ecec322cb2f3eff85a. Stop the container before attempting removal or force remove
ERRO[0003] error waiting for container: context canceled
Occasionally it happens even in this version with 10 parallels of 100 iterations.
After all, this loop didn't end, but I stopped because I could only find about 10 new names for each epoch. We will find the law here.
It's said to be an analysis, but I just look at the extracted container names and think that there seems to be a law like this.
The number of names found is `` `25422. There are likely to be hundreds more undiscovered names. The name always contains an underscore (
_```), which seems to be the character that separates the preceding and following words. Let's list this word. Also, this word does not seem to be duplicated before and after, so I will list it separately.
sed -e 's/_.*//g' names > names_first
uniq names_first names_first_uniq
Since the word after it must be sorted, the command used in the above extraction script is used.
sed -e 's/.*_//g' names > names_second
sort -u names_second -o names_second_uniq
Assuming that there are no words that have not yet appeared, I guess that the container name is created by combining these 108 x 350 words.
In that case, the number of combinations will be 37800
, so I regret that the script was inefficient and the number of trials was not enough.
I followed the source code, relying on the words extracted above.
https://github.com/moby/moby/blob/master/pkg/namesgenerator/names-generator.go
It seems that the outline was captured, but it was not what I expected. Depending on the combination of __108 x 237 words and the number of retries given as an argument, a number from 0 to 9 was randomly added to the end __.
(However, except for the combination of boring
and wozniak
)
In response to this, out of the 350 trailing words I extracted, excluding the ones with numbers, the number is exactly 237. In other words, it seems that all the candidate words could be extracted before and after.
However, the total number of theoretical combinations, including the numbers given at random, is (108 * 237-1) * 11 = 281545
(and the probability of giving numbers is low), which is tremendous. So I stopped and it was the correct answer.
That's it. I was curious about it, but it was a meaningful survey because I learned a lot (especially about shells) while I was researching it.