This is a series blogs about Docker and Kubernetes — This is the 2nd blog following up to my first one.
After getting the concepts there in the last blog, this time we will learn about some essential commands in different situations.
Manage Containers using Docker Client
— create and run a container from a image
docker run <image name>
$ docker run busybox
this is a combination of docker create and docker start-- create and run a image with a command (to override default command)
docker run <image name> command
$ docker run busybox echo hi there-- list all running containers
$ docker ps -all-- create a container:copy FS snapshot and paste into hard drive segment
docker create <imagename>
$ docker create hello-world
$ a2d84298351ae5ca6bb5845571f82fd3899f35762b7ebb1c459727cc3b7535bf-- run the container:copy the startup command and paste and run it
docker run <imageid>
$ docker run a2d84298351ae5ca6bb5845571f82fd3899f35762b7ebb1c459727cc3b7535bf
$ hello from Docker!-- delete all previous(cached)containers
docker system prune -- get logs from container
docker logs <container id>
$ docker logs a2d84298351ae5ca6bb5845571f82fd3899f35762b7ebb1c459727cc3b7535bf-- stop container from running
docker stop <container id> --> send SIGTERM (let itself shut down and do some clean up work)
docker kill <container id> --> send SIGKILL (force container kill itself)-- execute command in running containers
docker exec -it <container id> <command>
$ docker exec -it f3b57b8e7472 redis-cli
-i tag attach the terminal
-t tag make it faster
running a command in the container-- get access to the shell of the running container
docker exec/run -it <container id> shdocker run -it busybox sh
/ # echo hello
/ #-- attach local standard input, output, and error streams to a running container
docker attach [OPTIONS] <container id>
Building Images using Docker Server
In order to build an image we would need a Dockerfile (configuration to define how the container behave).
- Dockerfile → Docker Client → Docker Sever → Usable image
- Specify a base image
- Run some command to install additional programs (images)
- Specify a command to run on container startup
In every step, create a temporary container of the last step image, and do its thing, and create a new clean image with all the executed result and delete the temporary container. For example, below example we are building a redis image:
# Use an existing docker image as baseFROM alpine# Download and install a dependency (create a temporary container A use the image listed in last step--alpine, and execute the command (in this case it's to download and update redis). In the end it will remove the temporary container A and create a new container B with the file Snapshot from the outcome of the command (in this case the redis program along with alpine's original file snapshot).RUN apk add — update redis# Tell the image what to do when it starts as a container (create a temporary container C using the file Snapshot of container B listed in last step and put the primary command (in this case [redis-server] )into C. It then create a copy D from C with the file snapshot and the primary command and delete C)CMD [“redis-server”]
Then in root directory with the Dockerfile, run below command to give the file to Docker cli to Docker daemon
$docker build .
$....Successfully built 50cd3190ceb9
But what if we want to change/insert images after the above been built. Docker allows you to rebuild using cache: Every time we add new image, Docker will only rerun from the change line on down.
What does this mean?
e.g. insert "
RUN apk add --update gcc" after "
update redis" is different from just before "
$docker build .$ Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM alpine
Step 2/4 : RUN apk add --update redis
---> Using cache
Step 3/4 : RUN apk add --update gcc
---> Running in ae55ac07973b
(1/10) Installing libgcc (9.2.0-r4)
(2/10) Installing libstdc++ (9.2.0-r4)
(3/10) Installing binutils (2.33.1-r0)
(4/10) Installing gmp (6.1.2-r1)
(5/10) Installing isl (0.18-r0)
(6/10) Installing libgomp (9.2.0-r4)
(7/10) Installing libatomic (9.2.0-r4)
(8/10) Installing mpfr4 (4.0.2-r1)
(9/10) Installing mpc1 (1.1.0-r1)
(10/10) Installing gcc (9.2.0-r4)
OK: 102 MiB in 25 packages
Removing intermediate container ae55ac07973b
Step 4/4 : CMD ["redis-server"]
---> Running in e81d6f52aca8
Removing intermediate container e81d6f52aca8
Successfully built 2f9d4f14638e
Tag an image
You may notice that for images we’ve built we have an ID like:2f9d4f14638e. This is not that convenient, so that’s why we have Docker tags. Docker tags create aliases to the ID of your image so you can reference it easily.(just like how Git tags refers to a particular commit).
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
$ docker tag 2f9d4f14638e elfi16/redis
To build and tag together, adding the
docker build -t image_name .
$ docker build -t elfi16/redis .
Share Images on Docker Hub
Docker Hub repositories allow you share container images with the wide community.
First sign up to the Docker Hub and create a repository. To push an image to Docker Hub, you must first name your local image using your Docker Hub username and the repository name that you created through Docker Hub on the web.
You can add multiple images to a repository by adding a specific
:<tag> to them (for example
docs/base:testing). If it’s not specified, the tag defaults to
Name your local images using one of these methods:
- When you build them, using
docker build -t <hub-user>/<repo-name>[:<tag>]
- By re-tagging an existing local image
docker tag <existing-image> <hub-user>/<repo-name>[:<tag>]
- By using
docker commit <existing-container> <hub-user>/<repo-name>[:<tag>]to commit changes
We were using the first method in above section:
$ docker build -t elfi16/redis .
Now push this repository to the registry designated by its name or tag.
$ docker push elfi16/redis
The image is then uploaded and you can check it in your Docker Hub repository.
🐠 🐟 🐡 🐠 🐟 🐡 🐠 🐟 🐡 🐠 🐟 🐡 🐠 🐟 🐡 🐠 🐟 🐡 🐠 🐟 🐡 🐠 🐟 🐡 🐠 🐟 🐡 🐠 🐟 🐡 🐠 🐟 🐡 🐠 🐟 🐡 🐠 🐟 🐡 🐠 🐟 🐡 🐠 🐟 🐡 🐠 🐟 🐡