Docker 核心思想:将应用整合到容器中并运行起来(容器化)
镜像用于创建容器,命令是希望容器运行的应用
下一篇: 【Docker学习笔记】通过Docker部署MariaDB并连接到Python程序
一、镜像命令
-
docker image pull <镜像名>:<标签>
拉取镜像 -
docker push
推送镜像 -
docker images
或docker image ls
查看本机镜像
repository:仓库,镜像名
tag:标签,版本号
image id:镜像ID,唯一
created:创建时间
size:镜像大小 -
docker image rm
删除本地的镜像 -
docker search
根据镜像名称搜索远程仓库中的镜像
二、容器命令
-
docker container run <具体容器> <运行在容器的程序>
启动容器
-d:后台模式,容器在后台运行,不会占用我们当前的控制台
-i:以交互模式运行容器(-it)
-t:为容器也创建一个命令行窗口
-P:(大写)指定宿主机的随机端口映射到容器内部的端口
-p:(小写)指定某个具体端口映射到容器内部端口
-v:指定宿主机与容器内部的目录映射,就是之前的数据卷所需要的参数,好实现数据的持久化和同步
–name=“mynginx”:为容器指定一个名称,如果没有指定,那就分配一个随机名称
eg. -p 8080:80,就是让Docker主机的8080端口映射到容器内的80端口,当有流量访问主机的8080端口时,流量会直接映射到容器内的80端口。(默认容器必须有一个外部的映射端口,不然访问不了) -
Ctrl+P+Q
断开Shell和容器之间的链接,退出后保持容器在后台处于运行状态 -
docker container ls
列出所有运行(UP)状态的容器
-a 包括停止(Exited)状态的容器 -
docker container exec -it <options> <container-name or container-id> <command/app>
允许用户在运行状态的容器中启动一个新进程,可以将Docker主机shell连接到一个运行中容器终端
e.g.docker container exec -it volt sh(linux)
docker container exec -it volt pwsh.exe(Windows) -
docker container stop <container id or container name>
停止容器,发送SIGTERM给容器内PID为1的进程,如果进程10s内没有得到清理并停止运行,会接着发送SIGKILL信号来强制停止容器,然后用docker container rm来完成删除 -
docker container inspect <container id or container name>
会显示容器的配置细节和运行时信息 -
docker container kill
强制停止容器 -
docker container restart
重启容器 -
docker container rm
删除容器
docker container rm $(docker container ls -aq) -f
删除全部容器(-f强制执行) -
docker build -t name:tag
使用Dockerfile构建镜像
三、运行容器
1.启动一个简单的容器
(1)检查docker运行
docker -version
->有报错 linux 无权限 usermod -aG docker <user>
添加,退出重登Shell
Linux检查docker状态:service docker status
或systemctl is-sctive docker
Windows:Get-Service docker
(2)启动容器
(已拉取镜像docker image pull ubuntu:latest
)
docker container run -it ubuntu:latest /bin/bash
启动镜像
- -it使容器具备交互性并与终端进行连接
- ubuntu:latest具体镜像
- /bin/bash运行在容器的程序
->Docker客户端选择合适的API调用Docker daemon
->Daemon搜索本地库存或从DockerHub拉取到本地
->daemon创建容器、运行应用
->Shell变为root@0025eecacc36:/#说明已位于容器内部
(3)主进程退出,容器也会退出
exit
退出BashShell,容器也终止
Ctrl+P+Q
退出容器但不终止容器运行:
root@0025eecacc36:/# datalab@datalabvm12:~$
docker container exec -it <container id> bash
重新连接到Docker,并创建新的Bash(container id通过docker container ls
查看)
此时输exit容器并不会终止,原Bash进程还在运行中
(4)停止并删除容器
docker container stop <container id>
docker container rm <container id>
2.容器的生命周期
创建-运行-休眠-销毁
多次停止、启动、暂停、重启容器
3.重启策略(–restart)进行容器的自我修复
(1)always
除非容器被明确停止(如docker container stop命令),否则该策略会一直尝试重启处于停止状态的容器,当daemon重启时,停止的容器也会被重启。
(2)unless-stoped
Docker daemon重启时,处于Stoped(Exited)状态的容器不会被重启。
(3)on-failure
退出容器且不返回0时重启容器,Docker daemon重启时,容器也会被重启。
四、应用容器化
1.编写应用代码->创建 Dockerfile->docker image build
Dockerfile e.g.
$cat Dockerfile
FROM alpine #以alpine镜像作为当前镜像基础,非元数据,新增镜像层
LABEL maintainer="nigelpoulton@hotmail.com" #指定维护者
RUN apk add --update nodejs nodejs-npm #安装Node.js和npm
COPY . /src #将应用代码复制到镜像中
WORKDIR /src #设置新的工作目录,元数据
RUN npm install #安装依赖包
EXPOSE 8080 #记录应用的网络端口,元数据
ENTRYPOINT ["node","./app.js"] #将app.js设置为默认运行的应用,元数据
docker image build -t web:latest . #不要遗忘(.),表示Docker在构建时使用当前目录作为作为构建上下文
2.实例演示:
编写一个Dockerfile,其中包含nginx。nginx用来暴露一个简单的HTML静态页面,内容是:
<font color="red">Hello, Datalab</font>
并且可以通过本机IP地址+80/8080端口访问。
-
将本机端口8080映射到容器内的80端口
-
本机再配置一个nginx,将本机8080端口映射到本机80端口
以下是操作步骤描述,包含Dockerfile文件内容:
1.检查dockers运行
docker version
2.新建文件夹DockerDemo,文件夹中新建Dockerfile文件,内容如下
FROM nginx
#基于nginx镜像
RUN echo '<font color="red">Hello, Datalab<font>' > /usr/share/nginx/html/index.html
#前端代码写入程序
EXPOSE 80
#暴露在容器的80端口
CMD ["nginx","-g","daemon off;"]
#启动nginx
3.拉取nginx镜像
docker image pull nginx
4.cd到DockerDemo文件夹,基于Dockerfile构建镜像
docker image build -t mynginx .
5.运行容器,让Docker主机的8080端口映射到容器内的80端口
docker run -d -p 8080:80 mynginx
6.配置本机nginx并修改nginx.conf文件
http {
...
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
proxy_pass http://127.0.0.1:8080/; #配置本地端口转发
}
...
}
}
}
3.推送镜像到仓库
docker login -u <user name>
登录docker image tag <current-tag> <new-tag\>
为指定镜像额外添加标签,不需要覆盖已存在标签,推送镜像一般采用:docker image tag <local imgae name> <user name>/<repository name>:<new image name>
docker image push <user name>/<repository name>:<image name>
推送镜像
镜像推送需要:①Registry 镜像服务仓库②Repository 镜像仓库③Tag 标签(默认:Registry=docker.io、Tag=lagtest)
e.g.
docker image tag web nigel/xxx:dev
#nigel用户没有web镜像仓库访问权限,尝试推送到nigel这个二级命名空间
docker push nigel/xxx:dev
4.运行应用程序
docker container run -d --name c1 -p 80:8080 web:latest
基于web:latest镜像,启动名为c1的容器,该容器将内部的8080端口与主机的80端口进行映射-> 因此可以在浏览器地址栏输入Docker主机的DNS名称或IP地址直接访问这个web应用
docker container ls
验证
docker image history
查看构建镜像的过程中都执行了哪些指令,有SIZE变动的指令会新建镜像层
观察docker image build
输出内容来了解镜像构建过程
运行临时容器->在该容器中运行Dockerfile中的指令->将指令运行结果保存为一个新的镜像层->删除临时容器
5.生成较小镜像
(1)写法
每个RUN指令会新增一个镜像层,可以使用&&连接多个命令以及使用反斜杠()换行将多个命令包含在一个RUN指令中。
(2)多阶段构建
多阶段构建仅用到一个Dockerfile,多个FROM,并且docker image build命令不需要增加额外参数。
COPY --from
从直接的阶段构建的镜像中仅复制生产环境相关的应用代码,而不会复制生产环境不需要的构建。
可以通过docker image build
增加 --nocache=true 强制忽略对缓存的使用
增加–squash来创建一个合并的镜像
五、DockerCompose
1.Docker-Compose安装(Linux)
$ sudo apt install docker-compose # version 1.25.0-1
$ docker-compose --version
2.Compose文件
使用 docker compose 运行多容器命令
version: '3' #定义docker compose版本
services: #定义需要运行的应用服务
app: #容器之一的自定义名称
image: node:latest #需要拉取的镜像
container_name: app_main #容器的名称
restart: always #重启策略
command: sh -c "yarn install && yarn start" #运行服务的命令
ports: #运行容器的自定义端口
- 8000:8000
working_dir: /app #服务容器的当前工作目录
volumes:
- ./:/app
environment: #定义环境变量,例如数据库凭据等
MYSQL_HOST: localhost
MYSQL_USER: root
MYSQL_PASSWORD:
MYSQL_DB: test
mongo:
image: mongo
container_name: app_mongo
restart: always
ports:
- 27017:27017
volumes:
- ~/mongo:/data/db
volumes: #指引Docker创建新的卷
mongodb:
- version:(必有、第一行)定义docker compose版本(主要为API)
- services:定义需要运行的应用服务(如web-fe、redis)
- app:容器之一的自定义名称
- image:需要拉取的镜像
- container_name:容器的名称
- restart:重启策略
- build:指定构建新镜像的Dockerfile的目录
- command:运行服务的命令
- port:运行容器的自定义端口
- working_dir:服务容器的当前工作目录
- environment:定义环境变量,例如数据库凭据等
- networks:指引Docker创建新的网络,默认创建bridge网络,使用driver属性指定不同的网络类型
- volumes:指引Docker创建新的卷
3.Compose命令
-
docker-compose build
构建多容器 -
docker-compose up
启动compose,默认查找docker-compose.yml或 .yaml文件
-f 指定.yml文件名docker-compose -f prod-equus-bass.yml up
-d 在后台启动,分离模式docker-compose up -d
& 将终端窗口返回docker-compose up &
-
docker-compose down
停止,关闭删除已启动容器 -
docker-compose ps
查看应用状态,显示容器名称、运行的Command、当前状态、监听的网络端口 -
docker-compose stop
停止应用,不删除资源 -
docker-compose rm
删除容器和网络,不删除卷、镜像、应用源码 -
docker-compose restart
重启应用
六、卷(Volume)
1.卷的基本命令
docker volume create <name>
创建新卷,默认使用local驱动,通过-d参数指定不同驱动docker volume ls
查看所有容器卷docker volume inspect
查看指定卷详细信息docker volume prune
删除未装入到容器或服务器的所有卷docker volume rm
删除指定卷,都不能删除正在被容器或服务使用的卷- 在Dockerfile中使用
VOLUME <container-mount> poinr
指令部署,每次部署都需指定主机目录
2.mount 挂载
docker container run -dit --name myvoltainer --mount source=my_volume,target=/vol mynginx
#将卷挂载到容器mynginx上,容器中内容放置在卷中/vol目录
docker container exec -it myvoltainer bin/bash
#链接到容器
root@a821e1b5002e:/# cd vol
root@a821e1b5002e:/vol# ls
50x.html index.html
3.-v挂载
e.g.(Linux)编写一个Dockerfile,其中用nginx暴露一个简单的HTML静态页面
创建一个名为myvol的卷
datalab@datalabvm12:/$ docker volume create myvol
查看卷信息
datalab@datalabvm12:/$ docker volume ls
DRIVER VOLUME NAME
local myvol
datalab@datalabvm12:/$ docker volume inspect myvol
[
{
"CreatedAt": "2023-08-15T06:21:22Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/myvol/_data",
"Name": "myvol",
"Options": null,
"Scope": "local"
}
]
编写Dockerfile(不建议写在opt目录下)
datalab@datalabvm12:/opt$ mkdir DockerDemo
datalab@datalabvm12:/opt$ cd DockerDemo
datalab@datalabvm12:/opt$ sudo vim Dockerfile
datalab@datalabvm12:/opt/DockerDemo$ cat Dockerfile
FROM nginx
RUN echo '<font color="red">Hello,Datalab<font>' > /usr/share/nginx/html/index.html
EXPOSE 80
CMD ["nginx","-g","daemon off;"]
datalab@datalabvm12:/opt/DockerDemo$ sudo docker image build -t mynginx .
-v挂载 <本地目录>:<容器内目录>
datalab@datalabvm12:/opt/DockerDemo$ sudo docker run -d -p 8048:80 \
-> --name mynginx \
-> -v /home/datalab/mynginx_html:/usr/share/nginx/html \
-> mynginx
743257b28e842a22b324c066a15930cce08751d035a4bd8b98fa073bd5a97f7b
七、dockers网络
1.docker网络基本命令
docker network ls
用于列出运行在本地Docker主机上的全部网络docker network inspect <netname>
提供Docker网络的详细配置信息docker network create <netname>
创建新的Docker网络
-d 参数指定驱动及网络类型(Windows默认NAT,Linux默认Bridge)docker network prune
删除Docker主机上所有未使用的网络docker network rm <netid>
删除Docker主机上的指定网络
2.单机桥接网络
在Linux主机,Bridge底层基于Linux Bridge,默认的"bridge"网络被映射到内核中为"docker0",通过标准Linux工具查看这些网络
datalab@datalabvm12:~$ docker network inspect bridge #底层信息
datalab@datalabvm12:~$ ip link show docker0 #通过标准Linux工具查看网络
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 02:42:d4:15:f9:3b brd ff:ff:ff:ff:ff:ff
datalab@datalabvm12:~$ docker network inspect bridge | grep bridge.name #通过docker network inspect观察输出内容
"com.docker.network.bridge.name": "docker0",
新建Linux网桥
datalab@datalabvm12:~$ docker network create -d bridge localnet
312b67b11115a79d969c43d0868c30023a7db06174ce3806da3de247bb6b8240
新建一个名为c1的容器,接入网桥
datalab@datalabvm12:~$ docker container run -d --name c1 --network localnet alpine sleep 1d
af13a8ea4baf82db559343f5d24642d9d5f7198443eac87e17d14a22c6270075
创建一个名为c2的容器,接入c1所在的localnet网络ping c1,成功
datalab@datalabvm12:~$ docker container run -it --name c2 --network localnet alpine sh
/ # ping c1
PING c1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.121 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.078 ms
^C
学习参考
一文看懂-Docker容器化
九步构建自己的hello world Docker镜像
【docker系列】逐行解析Nginx镜像Dockerfile(学习经典)
静态页面+Nginx容器化Dockerfile
Nginx详解,睡前十分钟啃完值了
Linux post-installation steps for Docker Engine
实战案例:Dockerfile 直接制作nginx镜像
nginx -g “daemon off;” 你学废了吗
菜鸟Docker Dockerfile
深入浅出Docker