Docker
Docker底层的虚拟化技术依赖的是LXC(Linux container),LXC封装了cgroups和namespace这些内核特性。
安装Docekr
这里我使用的是Ubuntu系统安装Docker
Docker官方的安装教程 docs.docker.com/engine/inst…
更新软件列表
$ sudo apt update
添加必备的软件包
$ sudo apt install apt-transport-https ca-certificates curl software-properties-common
添加 Docker 的官方 GPG 密钥
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
将 Docker 版本库添加到APT源
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
再次更新软件包
$ sudo apt update
确定是在Docker版本库下载 download.docker.com
$ apt-cache policy docker-ce
下载域名是Docker的
root@ubuntu:/var/lib/docker# apt-cache policy docker-ce
docker-ce:
Installed: 5:20.10.12~3-0~ubuntu-focal
Candidate: 5:20.10.12~3-0~ubuntu-focal
Version table:
*** 5:20.10.12~3-0~ubuntu-focal 500
500 https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
100 /var/lib/dpkg/status
5:20.10.11~3-0~ubuntu-focal 500
500 https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
5:20.10.10~3-0~ubuntu-focal 500
500 https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
5:20.10.9~3-0~ubuntu-focal 500
上面确认完毕就可以安装Docker了
$ sudo apt install docker-ce
启动Docker守护程序,查看运行情况
sudo systemctl status docker
root@ubuntu:/var/lib/docker# sudo systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2022-01-09 21:45:11 PST; 1h 3min ago
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
Main PID: 1175 (dockerd)
Tasks: 22
Memory: 109.5M
CGroup: /system.slice/docker.service
└─1175 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
删除旧版本Docker
$ sudo apt-get remove docker docker-engine docker.io containerd runc
卸载Docekr
$ sudo apt-get purge docker-ce docker-ce-cli containerd.io
删除映像 卷 和容器
$ sudo rm -rf /var/lib/docker
$ sudo rm -rf /var/lib/containerd
如果无法删除请尝试root用户
Docker换源
首先进入/etc/docker$目录,找到daemon.json文件如果有的话直接修改没有的话创建一个。
$ cd /etc/docker
$ vim daemon.json
我这里直接创建一个
{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://ustc-edu-cn.mirror.aliyuncs.com",
"https://ghcr.io",
"https://mirror.baidubce.com"
],
"dns": ["8.8.8.8","8.8.4.4"]
}
然后把上面的内容写进去,各位可以找一些速度比较快的源替换。
然后重启Docker
$ service docker restart
让使用Docker命令时不需要添加sudo
sudo groupadd docker #添加docker用户组\
sudo gpasswd -a $USER docker #将登陆用户加入到docker用户组中\
newgrp docker #更新用户组
使用Docker创建HelloWorld
首先我们下载我们需要的镜像,下载镜像可以到hub.docker.com/。
找到需要的镜像里面会显示下载镜像要使用的命令。
docker pull hello-world
也可以通过命令进行搜索
kuman@ubuntu:/$ sudo docker search Hello
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
hello-world Hello World! (an example of minimal Dockeriz… 1623 [OK]
tutum/hello-world Image to test docker deployments. Has Apache… 87 [OK]
nginxdemos/hello NGINX webserver that serves a simple page co… 82 [OK]
openshift/hello-openshift Simple Example for Running a Container on Op… 39
dockercloud/hello-world Hello World! 19 [OK]
karthequian/helloworld A simple helloworld nginx container to get y… 17 [OK]
crccheck/hello-world Hello World web server in under 2.5 MB 15 [OK]
hello-seattle Hello from DockerCon 2016 (Seattle)! 8 [OK]
strm/helloworld-http A hello world container for testing http bal… 6 [OK]
arm32v7/hello-world Hello World! (an example of minimal Dockeriz… 3
ppc64le/hello-world Hello World! (an example of minimal Dockeriz… 2
wouterm/helloworld A simple Docker image with an Nginx server … 1 [OK]
kimb88/hello-world-spring-boot Hello World Spring Boot 1
ansibleplaybookbundle/hello-world-db-apb An APB which deploys a sample Hello World! a… 1 [OK]
ansibleplaybookbundle/hello-world-apb An APB which deploys a sample Hello World! a… 1 [OK]
cy4n/hello springboot hello playground 1
datawire/hello-world Hello World! Simple Hello World implementati… 1 [OK]
yanzhi/helloworld Hello World 0
dongxuny/hellotencent Auto build 0 [OK]
aosqe/hello-openshift https://github.com/jhou1/hello-openshift 0
milsonian/hellohttp Basic hello world http app in golang 0 [OK]
widdix/hello Hello World! 0
ocpqe/hello-pod Copy form docker.io/deshuai/hello-pod:latest 0
hivesolutions/hello_appier Simple hello world application for Appier. 0 [OK]
silasbw/hello
使用sudo docker pull 镜像名进行下载。
因为我已经下载过了所以只会获取一次是否是最新版本。
Using default tag: latest
latest: Pulling from library/hello-world
Digest: sha256:975f4b14f326b05db86e16de00144f9c12257553bba9484fed41f9b6f2257800
Status: Image is up to date for hello-world:latest
docker.io/library/hello-world:latest
我们再来下载一个mysql镜像。
sudo docker pull mysql
下载完成是这个样子。
Using default tag: latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
e5c707858ec0: Pull complete
fc41578cbf60: Pull complete
4785d896ef10: Pull complete
7d250cdc93be: Pull complete
309700f41983: Pull complete
45fd33301836: Pull complete
92f970c68b71: Pull complete
bb3544339a9e: Pull complete
f66ddf4c43fa: Pull complete
Digest: sha256:d0507b008897c39f6cbc76285af1171d4551988475e00e91344060023cd9c553
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest
然后用sudo docker images命令查看一下我们下载好的镜像
我这里现在有三个镜像,mysql ubuntu 和helloworld。
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql latest 5b4c624c7fe1 19 hours ago 519MB
ubuntu latest d13c942271d6 13 days ago 72.8MB
hello-world latest feb5d9fea6a5 3 months ago 13.3kB
这里的镜像就和我们装系统的ISO文件一样。
cn_windows_10_multiple_editions_version_1703_updated_july_2017_x64_dvd_10925382.iso
这是一个WIndows10系统的镜像文件名称,我们可以下载这个镜像给我们的主机装入windows10系统,可以在MSDN下载镜像
我们可以使用系统镜像给多台计算机装入系统,当然这个在Docker中也一样,我们可以使用镜像创建多个容器,这里的容器就类似我们的多台服务器主机,只不过是通过虚拟出来的。
接下来我们开始运行一个HelloWorld镜像的容器。
kuman@ubuntu:/$ sudo docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
学习Docekr
基本概念
在docker中有三个比较重要的名词,镜像、容器、仓库、以及卷。
镜像可以被理解为一个只读的模板,而容器则是通过镜像创建出来的实体。我们可以通过向容器内添加软件或文件再次将容器变为镜像,仓库则是用来存储这些镜像的服务器,使用最多的是Docker Hub,Docker中,要想实现数据的持久化就要使用到卷这个东西了,我们可以通过吧主机的文件位置挂载到容器中使用,并且在容器的声明周期结束时,卷中的数据也不会消失,就好像将一块固态硬盘连到了一台虚拟机上的感觉。
容器的五种状态
- Created:容器已经被创建,容器所需的相关资源已经准备就绪,但容器中的程序还未处于运行状态。
- Running:容器正在运行,也即容器中的应用正在运行。
- Paused:容器已暂停,表示容器中的所有程序都处于暂停状态。
- Stopped:容器处于停止状态,占用的资源和沙盒环境都依然存在,只是容器中的应用程序均已停止。
- Deleted:容器已删除,相关占用的资源及存储在Docker中的管理信息也都已释放和移除。
容器的生命周期操作
我们可以使用 sudo docker ps -a命令来查看全部容器的运行状态以及其他信息。
这里如果不了解$()这个的话可以先去看一下shell。
在查看全部容器之前我使用sudo docker rm $(sudo docker ps -aq)命令删除了全部停止的容器。
kuman@ubuntu:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
可以看到非常的干净,一个容器都没有。
接下来我们使用run命令来运行一个容器。
run
kuman@ubuntu:~$ sudo docker run ubuntu echo 'Hello world'
Hello world
这里我有几个已经下好的镜像
kuman@ubuntu:~$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql latest 5b4c624c7fe1 9 days ago 519MB
ubuntu latest d13c942271d6 3 weeks ago 72.8MB
ubuntu 18.04 886eca19e611 3 weeks ago 63.1MB
hello-world latest feb5d9fea6a5 4 months ago 13.3kB
如果我们不在镜像后面加 :版本号 的话就会使用最新的镜像创建容器
如果想用指定版本的话我们可以这样
sudo docker run ubuntu:18.04 /bin/echo 'Hello world'
这时我们已经创建并运行了两个容器
kuman@ubuntu:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
932cb081c4f0 ubuntu:18.04 "/bin/echo 'Hello wo…" 3 minutes ago Exited (0) 3 minutes ago great_tesla
70e5c432aa2f ubuntu "echo 'Hello world'" 7 minutes ago Exited (0) 7 minutes ago great_liskov
因为我们运行容器后执行shell脚本的速度非常的快,所以运行结束后容器直接就变成了Exited(退出状态)。
守护态运行容器
kuman@ubuntu:~$ sudo docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
eafaf0e0eeec3785a2e5ef92ccc95e0f1a0d2299676e2e7e826a60c0b784a35c
kuman@ubuntu:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eafaf0e0eeec ubuntu "/bin/sh -c 'while t…" 15 seconds ago Up 14 seconds keen_hellman
上面我运行了一个可以死循环的shell脚本。
可以看到我们的状态变成了容器的运行时间。
我们平时可以通过加参数docker run -dit ubuntu启动容器。
create
我们可以使用 docker create 创建容器而不去启动。
kuman@ubuntu:~$ sudo docker create --name 0x01 ubuntu
d26aa32697d5111d75a014c1b575e059161956013ab69ef1e33d22b9837512d6
kuman@ubuntu:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d26aa32697d5 ubuntu "bash" 3 seconds ago Created 0x01
上面这条命令我们使用create命令创建了一个未启动的容器
kuman@ubuntu:~$ sudo docker create --name 0x01 ubuntu echo "hello world"
b528f1ce66549416baff86f1d376e247cfe94ecf08baa5920d20e706f0f2a96f
kuman@ubuntu:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b528f1ce6654 ubuntu "echo 'hello world'" 7 seconds ago Created 0x01
kuman@ubuntu:~$ sudo docker start b528f1ce6654
b528f1ce6654
kuman@ubuntu:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b528f1ce6654 ubuntu "echo 'hello world'" 29 seconds ago Exited (0) 2 seconds ago 0x01
start
然后我们使用docker start 命令启动该容器,后面的参数可以使用ID或者name。
docker run 命令相当于将create和start 这两条命令进行了整合,可以让我们更方便的启动运行容器。
kill
接下来在来了解一下kill命令
kuman@ubuntu:/$ sudo docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
76e412b6a8701e5beb0a99a946ec769580b579dc63ebde98a392cec43114930d
kuman@ubuntu:/$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
76e412b6a870 ubuntu "/bin/sh -c 'while t…" 10 seconds ago Up 9 seconds eager_haslett
kuman@ubuntu:/$ sudo docker kill 76e412b6a870
76e412b6a870
kuman@ubuntu:/$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
76e412b6a870 ubuntu "/bin/sh -c 'while t…" 30 seconds ago Exited (137) 1 second ago eager_haslett
kuman@ubuntu:/$
kill命令可以让容器直接进入Exited状态,即退出。
stop
stop命令和kill命令非常的相似。
kuman@ubuntu:/$ sudo docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
55df7c0bc57152b60589b4e34ee521d2701e1cfbf26754fe6aa6691c8970e154
kuman@ubuntu:/$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55df7c0bc571 ubuntu "/bin/sh -c 'while t…" 7 seconds ago Up 6 seconds heuristic_lichterman
kuman@ubuntu:/$ sudo docker stop 55df7c0bc571
55df7c0bc571
kuman@ubuntu:/$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55df7c0bc571 ubuntu "/bin/sh -c 'while t…" 35 seconds ago Exited (137) 4 seconds ago heuristic_lichterman
这里使用stop命令将容器停止,看起来和kill并没有什么区别,但是设计师肯定不会设计两个功能一样的命令吧。
我们使用help命令看一下。
kuman@ubuntu:/$ sudo docker stop --help
Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...]
Stop one or more running containers
Options:
-t, --time int Seconds to wait for stop before killing it (default 10)
kuman@ubuntu:/$ sudo docker kill --help
Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...]
Kill one or more running containers
Options:
-s, --signal string Signal to send to the container (default "KILL")
stop命令可以可以通过参数设置定时停止,而kill命令的却是向容器发送文字串。
docker stop,支持“优雅退出”。先发送SIGTERM信号,在一段时间之后(10s)再发送SIGKILL信号。Docker内部的应用程序可以接收SIGTERM信号,然后做一些“退出前工作”,比如保存状态、处理当前请求等。
docker kill,发送SIGKILL信号,应用程序直接退出。
上面引用了网上其他人说的一些区别,所以在退出时还是要使用stop命令更加的安全。
restart
kuman@ubuntu:/$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55df7c0bc571 ubuntu "/bin/sh -c 'while t…" 10 minutes ago Exited (137) 9 minutes ago heuristic_lichterman
kuman@ubuntu:/$ sudo docker restart 55df7c0bc571
55df7c0bc571
kuman@ubuntu:/$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55df7c0bc571 ubuntu "/bin/sh -c 'while t…" 10 minutes ago Up 1 second heuristic_lichterman
kuman@ubuntu:/$ sudo docker restart 55df7c0bc571
55df7c0bc571
kuman@ubuntu:/$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55df7c0bc571 ubuntu "/bin/sh -c 'while t…" 11 minutes ago Up 2 seconds heuristic_lichterman
kuman@ubuntu:/$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55df7c0bc571 ubuntu "/bin/sh -c 'while t…" 11 minutes ago Up 18 seconds heuristic_lichterman
kuman@ubuntu:/$ sudo docker restart 55df7c0bc571
55df7c0bc571
kuman@ubuntu:/$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55df7c0bc571 ubuntu "/bin/sh -c 'while t…" 12 minutes ago Up 2 seconds heuristic_lichterman
kuman@ubuntu:/$
restart命令也就和翻译一样,将容器重新启动。当然不论是在运行状态还是关闭状态都可以重启启动。
rm
kuman@ubuntu:/$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55df7c0bc571 ubuntu "/bin/sh -c 'while t…" 16 minutes ago Exited (137) 27 seconds ago heuristic_lichterman
kuman@ubuntu:/$ sudo docker rm 55df7c0bc571
55df7c0bc571
kuman@ubuntu:/$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
kuman@ubuntu:/$
rm命令我们已经使用很多次了,就是将容器直接删除掉了,rm还有三个可以使用的参数,这里我们先了解一下。
kuman@ubuntu:/$ sudo docker rm --help
Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...]
Remove one or more containers
Options:
-f, --force Force the removal of a running container (uses SIGKILL) 强制删除容器
-l, --link Remove the specified link 移除容器间的网络连接
-v, --volumes Remove anonymous volumes associated with the container 删除与容器关联的卷
pause
这个命令可以将容器内的进程全部暂停服务。
kuman@ubuntu:/$ sudo docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
57774ea804b258be18713e0066e7ae43f931357009f94a120c105b4212d83c68
kuman@ubuntu:/$ docker logs -f 57774ea804b258be18713e0066e7ae43f931357009f94a120c105b4212d83c68
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/57774ea804b258be18713e0066e7ae43f931357009f94a120c105b4212d83c68/json": dial unix /var/run/docker.sock: connect: permission denied
kuman@ubuntu:/$ sudo docker logs -f 57774ea804b258be18713e0066e7ae43f931357009f94a120c105b4212d83c68
hello world
hello world
hello world
hello world
hello world
hello world
hello world
我们开启一个无限循环的shell命令,让他一直输出hello world,然后通过logs工具查看状态,可以看到命令行一直在输出hello world。
kuman@ubuntu:/$ sudo docker pause 57774ea804b258be18713e0066e7ae43f931357009f94a120c105b4212d83c68
57774ea804b258be18713e0066e7ae43f931357009f94a120c105b4212d83c68
kuman@ubuntu:/$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
57774ea804b2 ubuntu "/bin/sh -c 'while t…" 2 minutes ago Up 2 minutes (Paused) funny_satoshi
kuman@ubuntu:/$
然后我们使用pause命令将容器暂停,在使用logs工具查看一下。
kuman@ubuntu:/$ sudo docker logs -f 57774ea804b258be18713e0066e7ae43f931357009f94a120c105b4212d83c68
hello world
hello world
hello world
shell已经输出了很多hello world,但是暂停之后滚动条没有持续增长说明进程是真的被暂停了。
unpause
解除暂停
kuman@ubuntu:/$ sudo docker unpause 57774ea804b258be18713e0066e7ae43f931357009f94a120c105b4212d83c68
57774ea804b258be18713e0066e7ae43f931357009f94a120c105b4212d83c68
kuman@ubuntu:/$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
57774ea804b2 ubuntu "/bin/sh -c 'while t…" 6 minutes ago Up 6 minutes funny_satoshi
容器变回了运行状态,并且又开始持续输出了。
进入容器执行命令
attach
kuman@ubuntu:~$ sudo docker run -itd ubuntu
881c12b34bbfa65403465d46e40aca050ae8b3e279b7d47e36d3b97de6503c6f
kuman@ubuntu:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
881c12b34bbf ubuntu "bash" 5 seconds ago Up 4 seconds nice_chaum
kuman@ubuntu:~$ sudo docker attach 881c
root@881c12b34bbf:/#
kuman@ubuntu:~$ sudo docker attach 881c
root@881c12b34bbf:/# exit
exit
kuman@ubuntu:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
881c12b34bbf ubuntu "bash" 4 minutes ago Exited (130) 2 seconds ago nice_chaum
注意: 在这里使用exit退出终端会导致容器关闭如果想要退出容器终端并且保持运行请使用ctrl+P+Q组合键退出。
exec
kuman@ubuntu:~$ sudo docker exec -i 881c echo hello
hello
kuman@ubuntu:~$ sudo docker exec -it 881c echo hello
hello
kuman@ubuntu:~$ sudo docker exec -it 881c bash
root@881c12b34bbf:/# exit
exit
kuman@ubuntu:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
881c12b34bbf ubuntu "bash" 11 minutes ago Up 2 minutes nice_chaum
kuman@ubuntu:~$
注意: 在从exec命令进入容器时使用exit不会将容器停止。
登录DockerHub并发布镜像
我们可以使用docker login命令登录DockerHub的库
kuman@ubuntu:/$ sudo docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: pilipaladexiaolu
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
登录成功
可以使用docker logout命令退出登录
kuman@ubuntu:/$ sudo docker logout
Removing login credentials for https://index.docker.io/v1/
我们先创建一个容器在里面安装好一些工具。
使用docker commit命令将容器变为镜像。
kuman@ubuntu:/$ sudo docker commit 4e546e270654 kuman/ubuntu
sha256:81748c62e355201e32d38b3b48ee2bea8d2df15a0c03feddfe2a973924d62eeb
kuman@ubuntu:/$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
kuman/ubuntu latest 81748c62e355 8 seconds ago 114MB
mysql latest 5b4c624c7fe1 2 weeks ago 519MB
ubuntu latest d13c942271d6 4 weeks ago 72.8MB
ubuntu 18.04 886eca19e611 4 weeks ago 63.1MB
hello-world latest feb5d9fea6a5 4 months ago 13.3kB
可以看到镜像目录里多了一个我们自己提交的镜像。
kuman@ubuntu:/$ sudo docker run -it kuman/ubuntu
root@c5df872bcecd:/# ping www.baidu.com
PING www.a.shifen.com (39.156.66.14): 56 data bytes
64 bytes from 39.156.66.14: icmp_seq=0 ttl=127 time=20.518 ms
64 bytes from 39.156.66.14: icmp_seq=1 ttl=127 time=20.338 ms
64 bytes from 39.156.66.14: icmp_seq=2 ttl=127 time=20.671 ms
64 bytes from 39.156.66.14: icmp_seq=3 ttl=127 time=20.728 ms
64 bytes from 39.156.66.14: icmp_seq=4 ttl=127 time=20.779 ms
创建一个新的容器,使用一下刚刚保存在容器中下载的软件,可以看到都是存在的。
通过使用docker push命令将镜像提交到DockerHub中。 但是我们在push时镜像的名称是有条件的必须是DockerHub的用户名/镜像名
kuman@ubuntu:/$ sudo docker push pilipaladexiaolu/ubuntu
Using default tag: latest
The push refers to repository [docker.io/pilipaladexiaolu/ubuntu]
0fe21c04b2b5: Pushed
0eba131dffd0: Pushed
latest: digest: sha256:619b50ef583bc51b0f1cfabac351a8fbdda6cf3f660126327299a1ece6de23b0 size: 741
上传完成就是这个样子。
在DockerHub网站中也可以看到
docker search命令也可以搜索到。
删除本地镜像
docker image rm命令可以删除本地镜像
sudo docker rmi 可以简写
kuman@ubuntu:~$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
pilipaladexiaolu/ubuntu latest 81748c62e355 16 hours ago 114MB
mysql latest 5b4c624c7fe1 2 weeks ago 519MB
ubuntu latest d13c942271d6 4 weeks ago 72.8MB
ubuntu 18.04 886eca19e611 4 weeks ago 63.1MB
hello-world latest feb5d9fea6a5 4 months ago 13.3kB
kuman@ubuntu:~$ sudo docker rmi hello-world
Untagged: hello-world:latest
Untagged: hello-world@sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f
Untagged: hello-world@sha256:975f4b14f326b05db86e16de00144f9c12257553bba9484fed41f9b6f2257800
Deleted: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412
Deleted: sha256:e07ee1baac5fae6a26f30cabfe54a36d3402f96afda318fe0a96cec4ca393359
kuman@ubuntu:~$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
pilipaladexiaolu/ubuntu latest 81748c62e355 16 hours ago 114MB
mysql latest 5b4c624c7fe1 2 weeks ago 519MB
ubuntu latest d13c942271d6 4 weeks ago 72.8MB
ubuntu 18.04 886eca19e611 4 weeks ago 63.1MB
这样我们的本地镜像就被删掉了。
使用DockerFile构建镜像
使用docker commit生成镜像都是黑盒操作,开发者无法看到其中的细节,所以在生产过程中我们会使用docker bulid命令加DockerFile的方式生成镜像,这样即使是其他人也可以通过查看DockerFile查看具体过程。
首先我们在一个空白目录创建一个DockerFile文件
kuman@ubuntu:/opt/docker-file$ sudo touch Dockerfile
kuman@ubuntu:/opt/docker-file$ vim Dockerfile
使用Vim编辑工具对Dockerfile文件进行编辑
DockerFile命令在官网有文档详解,这里docs.docker.com/engine/refe…
FROM ubuntu
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install vim-gtk -y
添加这些文本,FROM 命令代表使用哪个镜像作为基础,RUN命令就是正常的linux的shell 会依次执行,这里输入-y参数是为了让apt自动回答是否继续安装,否则会中断安装过程。
Docker 还存在一个特殊的镜像,名为 scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。
这个镜像可以构建出超小镜像(文件大小),这里粗略带过,有兴趣可以自行了解。
kuman@ubuntu:/opt/docker-file$ sudo docker build -t pilipaladexiaolu/vim .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM ubuntu
---> d13c942271d6
Step 2/2 : RUN apt-get update && apt-get install vim-gtk
---> Running in fa18e010562d
Get:1 http://archive.ubuntu.com/ubuntu focal InRelease [265 kB]
Get:2 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Get:3 http://security.ubuntu.com/ubuntu focal-security/restricted amd64 Packages [960 kB]
Get:4 http://archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Get:5 http://archive.ubuntu.com/ubuntu focal-backports InRelease [108 kB]
Get:6 http://archive.ubuntu.com/ubuntu focal/multiverse amd64 Packages [177 kB]
Get:7 http://archive.ubuntu.com/ubuntu focal/main amd64 Packages [1275 kB]
...
Successfully tagged pilipaladexiaolu/vim:latest
打包成功。
将容器端口映射到主机端口
我们可以是用 -p参数将内部端口映射到外部
这里sudo docker run -d -p 80:80 -p 443:443 nginx可以设置多个端口映射前面是主机端口‘:’后面是容器内端口,这里不要搞混了。
查看容器信息
然后我们可以使用inspect命令查看一下容器信息
sudo docker inspect 09c5e23293e5577dac36741afbadc9c324a080dbc8be79d9579b683a1f9e8f1b
kuman@ubuntu:~$ sudo docker run -d -p 80:80 -p 443:443 nginx
09c5e23293e5577dac36741afbadc9c324a080dbc8be79d9579b683a1f9e8f1b
kuman@ubuntu:~$ sudo docker inspect 09c5e23293e5577dac36741afbadc9c324a080dbc8be79d9579b683a1f9e8f1b
[
{
"Id": "09c5e23293e5577dac36741afbadc9c324a080dbc8be79d9579b683a1f9e8f1b",
"Created": "2022-02-12T02:01:43.59524815Z",
"Path": "/docker-entrypoint.sh",
"Args": [
"nginx",
"-g",
"daemon off;"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 3996,
"ExitCode": 0,
"Error": "",
"StartedAt": "2022-02-12T02:01:43.854906447Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:c316d5a335a5cf324b0dc83b3da82d7608724769f6454f6d9a621f3ec2534a5a",
"ResolvConfPath": "/var/lib/docker/containers/09c5e23293e5577dac36741afbadc9c324a080dbc8be79d9579b683a1f9e8f1b/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/09c5e23293e5577dac36741afbadc9c324a080dbc8be79d9579b683a1f9e8f1b/hostname",
"HostsPath": "/var/lib/docker/containers/09c5e23293e5577dac36741afbadc9c324a080dbc8be79d9579b683a1f9e8f1b/hosts",
"LogPath": "/var/lib/docker/containers/09c5e23293e5577dac36741afbadc9c324a080dbc8be79d9579b683a1f9e8f1b/09c5e23293e5577dac36741afbadc9c324a080dbc8be79d9579b683a1f9e8f1b-json.log",
"Name": "/laughing_kapitsa",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "docker-default",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {
"443/tcp": [
{
"HostIp": "",
"HostPort": "443"
}
],
"80/tcp": [
{
"HostIp": "",
"HostPort": "80"
}
]
},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "host",
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/7a283fc1284343a5b4108341a9ad0e0346952b0a5d36ccf5ce18c4e691311e32-init/diff:/var/lib/docker/overlay2/a910c811e5c04efbedec685ce3a24142e1957b2a1c89b9133607223a1d932ec0/diff:/var/lib/docker/overlay2/8bb1f11d7033c07025fcd80a05b95b55dfbff61bbccb7894b679ddec0f6fd3f9/diff:/var/lib/docker/overlay2/14e99461049ea24124183b11cbd95f8b4b846763e0b682ce64f3fd5745cedcc1/diff:/var/lib/docker/overlay2/a3f2ae7fc4be42fa07b88a86db3706c29acb81968be2c0c4a2671d0dc147301d/diff:/var/lib/docker/overlay2/35afa0c19cb554dc42a651826ae3648f31e6cb0efafdc269a4d3cd94f100f214/diff:/var/lib/docker/overlay2/26bd41f4b30fb7d7164c534122997a02050ff6c0e99b380e7d04d218a641195f/diff",
"MergedDir": "/var/lib/docker/overlay2/7a283fc1284343a5b4108341a9ad0e0346952b0a5d36ccf5ce18c4e691311e32/merged",
"UpperDir": "/var/lib/docker/overlay2/7a283fc1284343a5b4108341a9ad0e0346952b0a5d36ccf5ce18c4e691311e32/diff",
"WorkDir": "/var/lib/docker/overlay2/7a283fc1284343a5b4108341a9ad0e0346952b0a5d36ccf5ce18c4e691311e32/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "09c5e23293e5",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"443/tcp": {},
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.21.6",
"NJS_VERSION=0.7.2",
"PKG_RELEASE=1~bullseye"
],
"Cmd": [
"nginx",
"-g",
"daemon off;"
],
"Image": "nginx",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"/docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
},
"StopSignal": "SIGQUIT"
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "72a84838ed7f8d045d7caef77d4791b35132639bc7e66aa1422dbe2f1f4eb8dc",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"443/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "443"
},
{
"HostIp": "::",
"HostPort": "443"
}
],
"80/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "80"
},
{
"HostIp": "::",
"HostPort": "80"
}
]
},
"SandboxKey": "/var/run/docker/netns/72a84838ed7f",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "83ccac785fcf721ce09bbf9eb0bc97ec3f7ab70d1f66a7e8c9d758fdad7b6d16",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "0873db9bf8dbb9dba5a0bbb5498d45a01e84079753bc9c689ac84d52f60d0a3a",
"EndpointID": "83ccac785fcf721ce09bbf9eb0bc97ec3f7ab70d1f66a7e8c9d758fdad7b6d16",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
我们也可以使用-f参数将容器的IP获取出来
kuman@ubuntu:~$ sudo docker inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" 09c5e23293e5577dac36741afbadc9c324a080dbc8be79d9579b683a1f9e8f1b
172.17.0.2
进阶Docker
上面简单叙述了我们一个初学者如何使用Docker进行安装以及使用,但是这是不够的。 Docker主要将命令分为了四个大类。
- 镜像
- 容器
- 文件存储
- 网络
docker-compose
当我们在使用微服务模式开发时会启动很多Docker容器,我们可以通过docker-compose对多个容器进行管理
安装
sudo apt install docker-compose
查看docker-composemingl
docker-compose --help
Define and run multi-container applications with Docker.
Usage:
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
docker-compose -h|--help
Options:
-f, --file FILE Specify an alternate compose file
(default: docker-compose.yml)
-p, --project-name NAME Specify an alternate project name
(default: directory name)
--verbose Show more output
--log-level LEVEL Set log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
--no-ansi Do not print ANSI control characters
-v, --version Print version and exit
-H, --host HOST Daemon socket to connect to
--tls Use TLS; implied by --tlsverify
--tlscacert CA_PATH Trust certs signed only by this CA
--tlscert CLIENT_CERT_PATH Path to TLS certificate file
--tlskey TLS_KEY_PATH Path to TLS key file
--tlsverify Use TLS and verify the remote
--skip-hostname-check Don't check the daemon's hostname against the
name specified in the client certificate
--project-directory PATH Specify an alternate working directory
(default: the path of the Compose file)
--compatibility If set, Compose will attempt to convert keys
in v3 files to their non-Swarm equivalent
--env-file PATH Specify an alternate environment file
Commands:
build Build or rebuild services
bundle Generate a Docker bundle from the Compose file
config Validate and view the Compose file
create Create services
down Stop and remove containers, networks, images, and volumes
events Receive real time events from containers
exec Execute a command in a running container
help Get help on a command
images List images
kill Kill containers
logs View output from containers
pause Pause services
port Print the public port for a port binding
ps List containers
pull Pull service images
push Push service images
restart Restart services
rm Remove stopped containers
run Run a one-off command
scale Set number of containers for a service
start Start services
stop Stop services
top Display the running processes
unpause Unpause services
up Create and start containers
version Show the Docker-Compose version information
如何使用docker-compose
docker-compose是通过yaml文件进行编排,如果不会yaml语法的同学可以看下面的网站。
简单举个例子,我们在工作目录下创建一个docker-compose.yaml文件
version: "3"
services:
web:
image: "nginx:latest"
ports:
- "80:80"
redis:
image: "redis:alpine"
将复制到docker-compose.yaml文件中
执行docker-compose up命令
可以看到已经成功执行了。
两个容器都存在。
如果需要编排一些高级的操作,可以看DockerCompose的官方手册
也可以看这个网站yeasy.gitbook.io/docker_prac…