Skip to content

Docker 的介绍

1. 为什么使用 Docker?

缺点优点
安装麻烦,可能有各种依赖、运行报错。例如:WordPress,Redis,Mysql 等。一行命令可以安装完毕,简单方便,有丰富的镜像可以直接使用
可能对 windows 并不友好,只支持在 Linux 运行没有系统兼容性问题,Linux 专享软件直接用
不方便安装多版本软件,不能共存支持软件多版本共存
安装了一堆软件,拖慢电脑运行速度用完就丢,不会拖慢电脑速度
不同系统和硬件,安装方式不一样安装好 Docker 不用担心环境,一个命令搞定所有

Docker 基本组成

名称描述
镜像相当于一个模板,通过模板来创建容器服务,通过镜像可以创建多个容器。
容器Docker 利用容器技术,独立运行一个或者一组应用,通过镜像来创建。启动,停止,删除,基本命令!目前可以把容器理解为一个简易的Linux 系统
仓库仓库是存放镜像的地方,分为公有仓库和私有仓库, Docker Hub(国外)阿里云、华为云、网易云、腾讯云...都有容器服务器(配置镜像加速)

容器(Container)技术的介绍

容器是一种快速的打包技术,主要有以下的特征:

  • 标准化

  • 轻量级

  • 易移植

注意

我们这里所说的容器 container 是指的一种技术,而 Docker 只是一个容器技术的实现,或者说让容器技术普及开来的最成功的实现。

为什么会出现容器技术

容器技术出现之前

容器技术出现之后

Docker 的架构

安装 Docker

在 Mac 上安装 Docker

请下载安装 Docker Desktop for Mac, 注意版本,地址在这里

  • Intel 芯片,请选择 Docker Desktop for Mac with Intel chip
  • M1 芯片,请选择 Docker Desktop for Mac with Apple silicon

在 Linux 上安装 Docker

温馨提示

此处的安装文档所处的系统环境为 CentOS8.4,不同的系统在安装方式上会存在些许的差距,请知悉。

shell
# 安装依赖
yum install -y yum-utils device-mapper-persistent-data lvm2

yum-utils:这是一个yum插件包,提供了一些额外的功能,用于更好地管理和维护yum的软件包。

device-mapper-persistent-data:这是一个设备映射持久化数据软件包,它提供了设备映射的持久化和恢复功能。

lvm2:这是逻辑卷管理器(LVM)的软件包,它允许您在Linux系统上创建、管理和扩展逻辑卷。


# 设置yum源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 或者使用阿里云的
$ yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo


# 安装docker
yum install -y docker-ce

指定版本号安装

格式 : yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io

例如安装19.03.12版本
yum install docker-ce-19.03.12 docker-ce-cli-19.03.12 containerd.io


# 设置开机启动
systemctl enable docker

# 启动 Docker
systemctl start docker

# 查看版本
docker version

特别注意:在 Centos8 中安装 docker 可能会报这样的错(Centos8 于 2021 年年底停止了服务):错误:Failed to download metadata for repo 'AppStream': Cannot prepare internal mirrorlist: No URLs in mirrorlist。解决的办法按照下面的步骤执行即可:

shell
# 1.进入yum的repos目录
cd /etc/yum.repos.d/

# 2.修改所有的CentOS文件内容,依次执行下面的两条命令
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*

sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*

# 3.更新yum源为阿里镜像
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo

# 如果wget提示没有安装的话,执行下面这条命令(其实到这步基本上已解决问题):
yum install wget -y

# 清除所有的缓存
yum clean all

# 把服务器的包信息下载到本地电脑缓存起来
yum makecache

# 4.测试是否安装成功
yum install wget –y

Image vs Container 镜像 vs 容器

Image 镜像

  • Docker image 是一个 read-only 文件
  • 这个文件包含文件系统,源码,库文件,依赖,工具等一些运行 application 所需要的文件
  • 可以理解成一个模板
  • docker image 具有分层的概念

Container 容器

  • 一个运行中的 docker image
  • 实质是复制 image 并在 image 最上层加上一层 read-write 的层 (称之为 container layer ,容器层)
  • 基于同一个 image 可以创建多个 container

Docker 快速上手

镜像的操作

1.拉取镜像

js
// 拉取node镜像
docker pull node:18
// 拉取mongodb镜像
docker pull mongo

2.查看镜像

  • docker images

  • docker image ls

shell
[root@casvfk5gmlqhxykb ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED      SIZE
node         latest    272b8142e84e   6 days ago   998MB
nginx        latest    3f8a00f137a0   7 days ago   142MB

3.删除镜像

  • docker rmi IMAGE ID
  • docker image rm IMAGE ID

注意

如果此镜像正在容器中运行,请不要删除!!!

shell
[root@casvfk5gmlqhxykb ~]# docker rmi 272b8142e84e
Untagged: node:latest
Untagged: node@sha256:33e99abf6cd64858bf5cc44824f1e50b7de61c9b9a3622c407951412a33fc28e
Deleted: sha256:272b8142e84e0290259f1bf8fe507419d984dc8db5717a1a3850e7551c289ad2
Deleted: sha256:4671a50c223c827e1920d360cf8162a9a444ac0fc7dbc46e6ae60d829d791d6d
Deleted: sha256:c8247c686190b87dec03c20af32c034558c7f7b311330c5b94708b6924825820
Deleted: sha256:37f47c53480da92a27caf45e6b0bb67e15d2ffc2ce26750ee9ece87968313e1d
Deleted: sha256:36ca113a7d30c59abf0870dcf652c59bc76cb627877d3e851619f65383a66b0f
Deleted: sha256:feef80ae1b9a4a49dfa5e41181caf683ab3dae44dc8b5c2fdafc4a4fb364d242
Deleted: sha256:35a162afcf7f923ad76bbcc532ebc3500d4c2fe2c045c2fc88e741a58197bf09
Deleted: sha256:9259e53dcd6f94d6d38111d2385de52014e38e4bfce49f5639fb3d6f9a58b430
Deleted: sha256:d78294ee5a46abcc2a8eb9bb1edb333604e57bd7cab95c8b9821038c6d506b1c
Deleted: sha256:8e396a1aad506affc6fa1b7c7b8ee75b54b78019e0a945e6ac52e3dc407e0766

4.查看镜像的详细信息

  • docker image inspect 镜像名称/镜像的 id
json
[root@casvfk5gmlqhxykb ~]# docker image inspect node
[
    {
        "Id": "sha256:272b8142e84e0290259f1bf8fe507419d984dc8db5717a1a3850e7551c289ad2",
        "RepoTags": [
            "node:latest"
        ],
        "RepoDigests": [
            "node@sha256:33e99abf6cd64858bf5cc44824f1e50b7de61c9b9a3622c407951412a33fc28e"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2023-02-11T01:49:40.539616245Z",
        "Container": "082c13b25c45efb827757b23c7a606f67e2538a660bf5a698ef89388a89b99e7",
        "ContainerConfig": {
            "Hostname": "082c13b25c45",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "NODE_VERSION=19.6.0",
                "YARN_VERSION=1.22.19"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"node\"]"
            ],
            "Image": "sha256:8aa3bcdfe255ee5eb322d21682c9d59bce0d208ae99a76e4668031bddb5994d6",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": {}
        },
        "DockerVersion": "20.10.12",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "NODE_VERSION=19.6.0",
                "YARN_VERSION=1.22.19"
            ],
            "Cmd": [
                "node"
            ],
            "Image": "sha256:8aa3bcdfe255ee5eb322d21682c9d59bce0d208ae99a76e4668031bddb5994d6",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 998294408,
        "VirtualSize": 998294408,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/a5800080fb85293eaffb4d539332e9409291582c752a29e11e054b6690d2df70/diff:/var/lib/docker/overlay2/165e71c6a8003661c38be0dc8d9df85224b9e6c227cc0aa5f76b47f9b63c6d1a/diff:/var/lib/docker/overlay2/acc6212c3a3df5cee9246191d23ef4a44e939cd47df14f7b422e81650c1c543d/diff:/var/lib/docker/overlay2/497abdeae83a13b72d529e62943ed0ed78c2def30cbb210d996d50e5da8888d0/diff:/var/lib/docker/overlay2/433b339efdeb4b7465cc34672fc94a53d6fdef2471903da7ef566476217d2c2a/diff:/var/lib/docker/overlay2/328331a6129a9ba16489310927d857969956e99f5d6a0bfe85e48c140c5b9699/diff:/var/lib/docker/overlay2/568bfff83c21cf7a94a6c7971ff4aa41b3b7c40fd646588c95966b359e6bc5d1/diff:/var/lib/docker/overlay2/787bd668e6e22a9ab33f44bb42a93bb80e56c04300f23fcb8857493516bec5f2/diff",
                "MergedDir": "/var/lib/docker/overlay2/eb59c9a289ee1b62571e53b8365280da539d007c26276ce61a26a7f6114857cf/merged",
                "UpperDir": "/var/lib/docker/overlay2/eb59c9a289ee1b62571e53b8365280da539d007c26276ce61a26a7f6114857cf/diff",
                "WorkDir": "/var/lib/docker/overlay2/eb59c9a289ee1b62571e53b8365280da539d007c26276ce61a26a7f6114857cf/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:8e396a1aad506affc6fa1b7c7b8ee75b54b78019e0a945e6ac52e3dc407e0766",
                "sha256:9d49e0bc68a4667c0e9626a6c6d52028c7bf4fc70aae065950ecf12ca16cf627",
                "sha256:dc8e1d8b53e9701a7b4ce09222181108f26772c8c4109737eebc49228533eb2f",
                "sha256:11829b3be9c01212cbca7374e6740e745f9908834bfe3d04770ced7840adf1a8",
                "sha256:0b6859e9fff186671725a31620f73c234f97973d4fa247ea184a968c3356a5c0",
                "sha256:4c92897e605e07d18c862183a5f22c20252ecb8f7dd286d162c627be6adc609e",
                "sha256:f0464d8bc9760305423f57ff1f8490cfe62a65766270ec6d4f896faa2cc4d290",
                "sha256:b2b5c714698d26de08da0986124407fecedab973126ae74f679145810e0ab318",
                "sha256:deb6581d20d51ab8d26e8749d77a9b5712553d4dfa6c01fead2fe1ed4b616fb3"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

容器的操作

1.创建(运行)一个容器

  • docker container run imageName
  • docker run imageName
  • 创建容器常见的参数
    • -i:交互式操作
    • -t:终端
    • -d:在后台运行
    • -p:对外映射端口,例如 8080:80 就是将容器的 80 端口映射为外部的 8080 端口访问
    • -P:随机映射容器 内的端口
    • --name:给当前运行的容器起一个方便使用的名字
shell
docker run -i -t -d -p 8080:80 --name nginx1 nginx

2.列出运行的容器

  • docker ps :列出运行中的容器
  • docker ps -a:列出所有的容器,包括运行中的和退出的
  • docker container ls -a:同 docker ps -a
shell
[root@casvfk5gmlqhxykb ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                   CREATED         STATUS         PORTS                                   NAMES
900d7b32896b   nginx     "/docker-entrypoint.…"   7 minutes ago   Up 7 minutes   0.0.0.0:8080->80/tcp, :::8080->80/tcp   admiring_edison
9e5040ee8314   nginx     "/docker-entrypoint.…"   3 hours ago     Up 3 hours     0.0.0.0:8888->80/tcp, :::8888->80/tcp   gifted_ganguly

3.停止容器

  • docker stop 容器的 ID:停止单个的容器
  • docker container stop 容器的 ID:同 docker stop
  • docker stop 容器 ID1 容器 ID2...:批量停止容器
  • docker stop $(docker ps -a -q):将所有运行中的容器全部停掉
shell
[root@casvfk5gmlqhxykb ~]# docker stop $(docker ps -a -q)
900d7b32896b
9e5040ee8314

4.删除容器

  • docker comtainer rm 容器 ID
  • docker rm 容器 ID(注意:删除镜像的简写命令是 docker rmi 镜像的名称/镜像的 ID)
  • 如果是运行中的镜像需要在上述的命令后面加-f 参数
  • docker rm 容器 ID1 容器 ID2...:批量删除容器
  • docker rm $(docker ps -a -q):删除全部的容器,默认只会删除已经停止运行的容器,如果需要删除正在运行中的,加-f 即可
shell
# 删除的容器ID可以取前面的几位即可
[root@casvfk5gmlqhxykb ~]# docker rm 032
032

5.查看运行中的容器的日志

  • docker logs -f 容器名称/容器 ID:持续读取容器的运行日志
shell
[root@casvfk5gmlqhxykb ~]# docker logs -f nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
101.82.191.147 - - [17/Feb/2023:06:00:07 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" "-"
101.82.191.147 - - [17/Feb/2023:06:00:07 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" "-"
101.82.191.147 - - [17/Feb/2023:06:00:07 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" "-"
101.82.191.147 - - [17/Feb/2023:06:00:07 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" "-"

6.进入到容器的内部(必须是运行中的状态)

  • docker exec -it 容器名称/容器 ID bash
shell
[root@casvfk5gmlqhxykb ~]# docker exec -it nginx bash
# 下面的新终端就是docker容器内部的终端
root@593f4f42106f:/#

7.docker run 背后发生了什么?

shell
docker run -itd -p 8080:80 --name nginx1 nginx
  1. 在本地查找是否有 nginx 这个 image 镜像,但是没有发现

  2. 去远程的 image registry 查找 nginx 镜像(默认的 registry 是 Docker Hub)

  3. 下载最新版本的 nginx 镜像 (nginx:latest 默认)

  4. 基于 nginx 镜像来创建一个新的容器,并且准备运行

  5. docker engine 分配给这个容器一个虚拟 IP 地址

  6. 在宿主机上打开 80 端口并把容器的 80 端口转发到宿主机上

  7. 启动容器,运行指定的命令(这里是一个 shell 脚本去启动 nginx)

构建自己的镜像

1.1 指令介绍

1.1.1 FROM

提示

功能为指定基础镜像,并且必须是第一条指令。如果不以任何镜像为基础,那么写法为:FROM scratch。同时意味着接下来所写的指令将作为镜像的第一层开始

shell
FROM <image>
FROM <image>:<tag>
FROM <image>:<digest>
# 三种写法,其中<tag>和<digest> 是可选项,如果没有选择,那么默认值为latest
1.1.2 ADD

提示

一个复制命令,把文件复制到镜像中。如果把虚拟机与容器想象成两台 linux 服务器的话,那么这个命令就类似于 scp,只是 scp 需要加用户名和密码的权限验证,而 ADD 不用。

  • 路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径,推荐写成绝对路径
  • 可以是一个本地文件或者是一个本地压缩文件,还可以是一个 url
  • 如果把写成一个 url,那么 ADD 就类似于 wget 命令
  • src 为一个目录的时候,会自动把目录下的文件复制过去,目录本身不会复制
  • 如果 src 为多个文件,dest 一定要是一个目录

语法如下:

shell
ADD <src>... <dest>
ADD ["<src>",... "<dest>"]
# 例如
ADD test/index.html /usr/local/nginx/html
1.1.3 COPY

提示

COPY 命令和 ADD 功能基本一致,唯一的区别是 COPY 命令拷贝的文件必须是本地文件,其他的用法一致。

shell
COPY <src>... <dest>
COPY ["<src>",... "<dest>"]
1.1.4 EXPOSE

提示

功能为暴漏容器运行时的监听端口给外部,但是 EXPOSE 并不会使容器访问主机的端口,如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上-p 参数

shell
EXPOSE <port端口>
1.1.5 ENV

提示

设置环境变量

shell
ENV <key> <value>
ENV <key>=<value> ...
1.1.6 RUN

提示

功能为运行指定的命令

shell
RUN <command>
# 例如:RUN npm install
RUN ["executable", "param1", "param2"]
# 例如:RUN ["npm", "install"]
1.1.7 CMD

提示

功能为容器启动时默认命令或参数。

特别需要主要 RUN 和 CMD 的区别:RUN 是构建容器时就运行的命令以及提交运行结果,CMD 是容器启动时执行的命令,在构建时并不运行,构建的时候仅仅指定了这个命令到底是个什么样子。

shell
CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2
1.1.8 编写完整的 Dockerfile
yaml
FROM nginx:latest
COPY ./index.html /usr/share/nginx/html
EXPOSE 80
EXPOSE 81
CMD ["nginx","-g", "daemon off;"]
1.1.9 构建自定义的 Docker 镜像
shell
# 镜像的名称必选,镜像的tag可选
# 后面的点表示Dockerfile文件在当前的目录下,且名字就叫Dockerfile
docker build -t 镜像名称:镜像的tag .

安装 docker-compose

使用 docker-compsoe 用来组合运行多个容器

shell
# 安装docker-compose(用于多个镜像之间的组合启动)
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 在执行docker-compose的时候,会报没有权限的错误(-bash: /usr/local/bin/docker-compose: Permission denied),执行下面的内容即可
chmod +x /usr/local/bin/docker-compose(docker-compose所在的路径)

# 查看是否安装成功
docker-compose version

# 在拥有docker-compose.yaml的文件夹执行下面的命令即可组合启动容器
docker-compose up -d

Docker 设置阿里镜像源

在控制台执行下面的命令即可

json
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://t5c1vjbg.mirror.aliyuncs.com"]
}
EOF

修改配置之后重启服务

shell
sudo systemctl daemon-reload
sudo systemctl restart docker
shell
# 启动
docker-compose start

# 查看运行的日志
docker-comose logs -f

# 停止
docker-comose stop

# 重启
docker-compose restart

# 停止并删除容器、网络
docker-compose down

# 停止并删除容器、网络和卷
docker-compose down --volumes

# 停止并删除容器、网络和所有服务使用的镜像,千万谨慎使用
docker-compose down --rmi all