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,不同的系统在安装方式上会存在些许的差距,请知悉。
# 安装依赖
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
。解决的办法按照下面的步骤执行即可:
# 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.拉取镜像
提示
Docker 的镜像拉取默认从https://hub.docker.com/中拉取,类似我们的npm镜像源下载,也可以指定资源的Docker镜像源进行下载。
// 拉取node镜像
docker pull node:18
// 拉取mongodb镜像
docker pull mongo
2.查看镜像
docker images
docker image ls
[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
注意
如果此镜像正在容器中运行,请不要删除!!!
[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
[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:给当前运行的容器起一个方便使用的名字
docker run -i -t -d -p 8080:80 --name nginx1 nginx
2.列出运行的容器
- docker ps :列出运行中的容器
- docker ps -a:列出所有的容器,包括运行中的和退出的
- docker container ls -a:同 docker ps -a
[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):将所有运行中的容器全部停掉
[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 即可
# 删除的容器ID可以取前面的几位即可
[root@casvfk5gmlqhxykb ~]# docker rm 032
032
5.查看运行中的容器的日志
- docker logs -f 容器名称/容器 ID:持续读取容器的运行日志
[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
[root@casvfk5gmlqhxykb ~]# docker exec -it nginx bash
# 下面的新终端就是docker容器内部的终端
root@593f4f42106f:/#
7.docker run 背后发生了什么?
docker run -itd -p 8080:80 --name nginx1 nginx
在本地查找是否有 nginx 这个 image 镜像,但是没有发现
去远程的 image registry 查找 nginx 镜像(默认的 registry 是 Docker Hub)
下载最新版本的 nginx 镜像 (nginx:latest 默认)
基于 nginx 镜像来创建一个新的容器,并且准备运行
docker engine 分配给这个容器一个虚拟 IP 地址
在宿主机上打开 80 端口并把容器的 80 端口转发到宿主机上
启动容器,运行指定的命令(这里是一个 shell 脚本去启动 nginx)
构建自己的镜像
1.1 指令介绍
1.1.1 FROM
提示
功能为指定基础镜像,并且必须是第一条指令。如果不以任何镜像为基础,那么写法为:FROM scratch。同时意味着接下来所写的指令将作为镜像的第一层开始
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 一定要是一个目录
语法如下:
ADD <src>... <dest>
ADD ["<src>",... "<dest>"]
# 例如
ADD test/index.html /usr/local/nginx/html
1.1.3 COPY
提示
COPY 命令和 ADD 功能基本一致,唯一的区别是 COPY 命令拷贝的文件必须是本地文件,其他的用法一致。
COPY <src>... <dest>
COPY ["<src>",... "<dest>"]
1.1.4 EXPOSE
提示
功能为暴漏容器运行时的监听端口给外部,但是 EXPOSE 并不会使容器访问主机的端口,如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上-p 参数
EXPOSE <port端口号>
1.1.5 ENV
提示
设置环境变量
ENV <key> <value>
ENV <key>=<value> ...
1.1.6 RUN
提示
功能为运行指定的命令
RUN <command>
# 例如:RUN npm install
RUN ["executable", "param1", "param2"]
# 例如:RUN ["npm", "install"]
1.1.7 CMD
提示
功能为容器启动时默认命令或参数。
特别需要主要 RUN 和 CMD 的区别:RUN 是构建容器时就运行的命令以及提交运行结果,CMD 是容器启动时执行的命令,在构建时并不运行,构建的时候仅仅指定了这个命令到底是个什么样子。
CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2
1.1.8 编写完整的 Dockerfile
FROM nginx:latest
COPY ./index.html /usr/share/nginx/html
EXPOSE 80
EXPOSE 81
CMD ["nginx","-g", "daemon off;"]
1.1.9 构建自定义的 Docker 镜像
# 镜像的名称必选,镜像的tag可选
# 后面的点表示Dockerfile文件在当前的目录下,且名字就叫Dockerfile
docker build -t 镜像名称:镜像的tag .
安装 docker-compose
使用 docker-compsoe 用来组合运行多个容器
# 安装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 设置阿里镜像源
在控制台执行下面的命令即可
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://t5c1vjbg.mirror.aliyuncs.com"]
}
EOF
修改配置之后重启服务
sudo systemctl daemon-reload
sudo systemctl restart docker
# 启动
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