Docker使用手册

316 阅读11分钟

Docker

linuxcontainers.org/

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 命令相当于将createstart 这两条命令进行了整合,可以让我们更方便的启动运行容器。

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

上传完成就是这个样子。

image.png

在DockerHub网站中也可以看到

image.png

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

image.png

打包成功。

将容器端口映射到主机端口

我们可以是用 -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语法的同学可以看下面的网站。

yaml语法教程

简单举个例子,我们在工作目录下创建一个docker-compose.yaml文件

version: "3"
services:
  web:
    image: "nginx:latest"
    ports:
      - "80:80"
  redis:
    image: "redis:alpine"

将复制到docker-compose.yaml文件中

执行docker-compose up命令

image.png

可以看到已经成功执行了。

image.png

两个容器都存在。

如果需要编排一些高级的操作,可以看DockerCompose的官方手册

也可以看这个网站yeasy.gitbook.io/docker_prac…