# Docker 实践
# 一、安装 Docker
# 1.1 Ubuntu 安装 Docker (opens new window)
# 1.2 macOS 安装 Docker (opens new window)
# 1.3 CentOS下安装Docker
# 安装Docker
sudo yum remove docker\*
sudo yum install -y yum-utils
#配置docker的yum地址
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#安装指定版本
sudo yum install -y docker-ce-20.10.7 docker-ce-cli-20.10.7 containerd.io-1.4.6
#yum install -y docker-ce docker-ce-cli containerd.io
# 启动&开机启动docker
systemctl enable docker --now
# docker加速配置
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://5j8ttgd9.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
# 修改docker Cgroup Driver为systemd 上面配置已经修改
#sed -i.bak "s#^ExecStart=/usr/bin/dockerd.*#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd#g" /usr/lib/systemd/system/docker.service
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 1.4 Debian下安装Docker
Install Docker Engine on Debian (opens new window)
# 二、镜像相关命令
# 2.1 获取镜像
Docker Hub (opens new window) 上有大量的高质量的镜像可以用。从 Docker 镜像仓库获取镜像的命令是 docker pull。其命令格式为:
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
- Docker 镜像仓库地址:地址的格式一般是
<域名/IP>[:端口号]
。默认地址是 Docker Hub。 - 仓库名:如之前所说,这里的仓库名是两段式名称,即
<用户名>/<软件名>
。对于 Docker Hub,如果不给出用户名,则默认为library
,也就是官方镜像。
示例:
docker pull ubuntu:18.04
docker pull nginx
2
# 2.2 列出镜像
列出已经下载下来的镜像
docker image ls
查看镜像、容器、数据卷所占用的空间 docker system df
列出特定的某个镜像 docker image ls ubuntu:18.04
看到在 mongo:3.2
之后建立的镜像 docker image ls -f since=mongo:3.2
想查看某个位置之前的镜像也可以,只需要把 since
换成 before
即可。
此外,如果镜像构建时,定义了 LABEL
,还可以通过 LABEL 来过滤。
$ docker image ls -f label=com.example.version=0.1
直接列出镜像结果,并且只包含镜像ID和仓库名
$ docker image ls --format "{{.ID}}: {{.Repository}}"
查看容器的存储层变动
docker diff
查看镜像内的历史记录
docker history nginx:v2
# 2.3 删除镜像
# 语法
docker image rm [选项] <镜像1> [<镜像2> ...]
# 删除虚悬镜像
docker image prune
docker image prune --force --all
# 删除所有镜像
docker image rm $(docker image ls --format "{{.ID}}")
# 删除所有仓库名为 redis 的镜像
docker image rm $(docker image ls -q redis)
# 或者删除所有在 mongo:3.2 之前的镜像
docker image rm $(docker image ls -q -f before=mongo:3.2)
2
3
4
5
6
7
8
9
10
11
# 2.4 创建镜像
Dockerfile
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
2
创建镜像
# 注意,最后一个点是 docker 的打包目录, docker 将该目录下所有的文件都打包进镜像。
docker build -t nginx:v3 -f nginx-Dockerfile .
2
# 2.5 提交改变
这里提交是在本地新增一个修改了的镜像
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
docker commit -a "leifengyang" -m "首页变化" 341d81f7504f guignginx:v1.0
2
3
# 2.6 镜像传输(镜像备份加载)
# 将镜像保存成压缩包
docker save -o abc.tar guignginx:v1.0
# 别的机器加载这个镜像
docker load -i abc.tar
2
3
4
5
# 2.7 推送远程仓库
推送镜像到docker hub;应用市场
docker tag local-image:tagname new-repo:tagname
docker push new-repo:tagname
2
# 把旧镜像的名字,改成仓库要求的新版名字
docker tag guignginx:v1.0 leifengyang/guignginx:v1.0
# 登录到docker hub
docker login
docker logout(推送完成镜像后退出)
# 推送
docker push leifengyang/guignginx:v1.0
# 别的机器下载
docker pull leifengyang/guignginx:v1.0
2
3
4
5
6
7
8
9
10
11
12
13
# 2.x 其他命令
# 查看镜像支持的环境变量
docker run IMAGE env
2
# 三、容器相关命令
# 3.1 启动容器
- 运行ubuntu容器
有了镜像后,我们就能够以这个镜像为基础启动并运行一个容器。以上面的 ubuntu:18.04 为例,如果我们打算启动里面的 bash 并且进行交互式操作的话,可以执行下面的命令。
$ docker run -it --rm \
ubuntu:18.04 \
bash
2
3
docker run
就是运行容器的命令,具体格式我们会在 容器 一节进行详细讲解,我们这里简要的说明一下上面用到的参数。
-it
:这是两个参数,一个是-i
:交互式操作,一个是-t
终端。我们这里打算进入 `bash`` 执行一些命令并查看返回结果,因此我们需要交互式终端。--rm
:这个参数是说容器退出后随之将其删除。ubuntu:18.04
:这是指用ubuntu:18.04
镜像为基础来启动容器。bash
:放在镜像名后的是 命令,这里我们希望有个交互式 Shell,因此用的是bash
。
- 启动nginx应用容器
# 启动nginx应用容器,并映射88端口,测试的访问
# -d:后台运行
# --restart=always: 开机自启
docker run --name=mynginx -d --restart=always -p 88:80 nginx
2
3
4
# 3.2 设置应用开机自启
docker update 容器id/名字 --restart=always
# 3.3 挂载数据到外部修改
docker run --name=mynginx \
-d --restart=always \
-p 88:80 -v /data/html:/usr/share/nginx/html:ro \
nginx
# 修改页面只需要去 主机的 /data/html
2
3
4
5
6
# 3.4 查看容器
# 查看正在运行的容器
docker ps
# 查看所有容器
docker ps -a
# 如何获取某个容器的 PID 信息
docker inspect --format '{{ .State.Pid }}' <CONTAINER ID or NAME>
何获取某个容器的 IP 地址
docker inspect --format '{{ .NetworkSettings.IPAddress }}' <CONTAINER ID or NAME>
# 列出所有容器ID
docker ps -aq
2
3
4
5
6
7
8
9
10
# 3.5 交互方式访问运行中的容器
docker exec -it CONTAINER bash
# 3.6 停止容器
docker stop 容器名
# 停止所有正在运行的容器
docker stop $(docker container ls -q)
2
3
# 3.7 删除容器
# 删除所有容器
docker rm $(docker ps -aq)
docker container rm 容器名
# 批量清理已经停止的容器
docker container prune
docker container prune -f
# 删除 exited 状态容器
docker rm $(docker ps --all -q -f status=exited)
2
3
4
5
6
7
8
9
10
# 3.8 容器网络设定
# 给容器指定一个固定 IP 地址,而不是每次重启容器 IP 地址都会变
$ docker network create -d bridge --subnet 172.25.0.0/16 my-net
$ docker run --network=my-net --ip=172.25.3.3 -itd --name=my-container busybox
# 临时退出一个正在交互的容器的终端,而不终止它
按 Ctrl-p Ctrl-q。如果按 Ctrl-c 往往会让容器内应用进程终止,进而会终止容器。
2
3
4
5
# 3.9 删除网络
docker network ls
docker network rm my_network
2
# 3.10 查看容器日志
docker logs 容器名/id
# 3.11 把容器指定位置的东西复制
#把容器指定位置的东西复制出来
docker cp 5eff66eec7e1:/etc/nginx/nginx.conf /data/conf/nginx.conf
#把外面的内容复制到容器里面
docker cp /data/conf/nginx.conf 5eff66eec7e1:/etc/nginx/nginx.conf
2
3
4
# 3.12 重启容器
docker restart 容器名
# 四、DockerFile
dockerfile 是 Docker 用来构建镜像的文本文件,包含自定义的指令和格式,可以通过 build 命令从 dockerfile 中构建镜像,命令格式为:docker build [OPTIONS] PATH | URL | -
。
dockerfile 描述了组装镜像的步骤,其中每条指令都是单独执行的。除了 FROM 指令,其他的每一条指令都会在上一条指令所生成镜像的基础上执行,执行完后会生成一个新的镜像层,新镜像层覆盖在原来的镜像之上从而形成新的镜像。为了提高镜像构建的速度, Docker Daemon 会缓存构建过程中的中间镜像。在构建镜像时,它会将 dockerfile 中下一条指令和基础镜像的所有子镜像做比较,如果有一个子镜像是由相同的指令生成的,则命中缓存,直接使用该镜像,而不用再生成一个新的镜像。常用指令如下:
# 4.1 FROM
FROM 指令用于指定基础镜像,因此所有的 dockerfile 都必须使用 FROM 指令开头。FROM 指令可以出现多次,这样会构建多个镜像,每个镜像创建完成后,Docker 命令行界面会输出该镜像的 ID。常用指令格式为:FROM <image>[:<tag>] [AS <name>]
。
# 4.2 MAINTAINER
MAINTAINER 指令可以用来设置作者名称和邮箱,目前 MAINTAINER 指令被标识为废弃,官方推荐使用 LABEL 代替。
# 4.3 LABEL
LABEL 指令可以用于指定镜像相关的元数据信息。格式为:LABEL <key>=<value> <key>=<value> <key>=<value> ...
。
# 4.4 ENV
ENV 指令用于声明环境变量,声明好的环境变量可以在后面的指令中引用,引用格式为 $variable_name
或 ${variable_name}
。常用格式有以下两种:
ENV <key> <value>
:用于设置单个环境变量;ENV <key>=<value> ...
:用于一次设置多个环境变量。
# 4.5 EXPOSE
EXPOSE 用于指明容器对外暴露的端口号,格式为:EXPOSE <port> [<port>/<protocol>...]
,您可以指定端口是侦听 TCP 还是 UDP,如果未指定协议,则默认为 TCP。
# 4.6 WORKDIR
WORKDIR 用于指明工作目录,它可以多次使用。如果指明的是相对路径,则它将相对于上一个WORKDIR指令的路径。示例如下:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd # 此时pwd为:/a/b/c
2
3
4
# 4.7 COPY
COPY 指令的常用格式为:COPY <src>... <dest>
,用于将指定路径中的文件添加到新的镜像中,拷贝的目标路径可以不存在,程序会自动创建。
# 4.8 ADD
ADD 指令的常用格式为:COPY <src>... <dest>
,作用与 COPY 指令类似,但功能更为强大,例如 Src
支持文件的网络地址,且如果 Src
指向的是压缩文件,ADD 在复制完成后还会自动进行解压。
# 4.9 RUN
RUN 指令会在前一条命令创建出的镜像基础上再创建一个容器,并在容器中运行命令,在命令结束后提交该容器为新的镜像。它支持以下两种格式:
RUN <command>
(shell 格式)RUN ["executable", "param1", "param2"]
(exec 格式)
使用 shell 格式时候,命令通过 /bin/sh -c
运行,而当使用 exec 格式时,命令是直接运行的,容器不调用 shell 程序,这意味着不会发生正常的 shell 处理。例如,RUN ["echo","$HOME"]
不会对 $HOME
执行变量替换,此时正确的格式应为:RUN ["sh","-c","echo $HOME"]
。下面的 CMD 指令也存在同样的问题。
# 4.10 CMD
CMD ["executable","param1","param2"]
(exec 格式, 首选)CMD ["param1","param2"]
(作为 ENTRYPOINT 的默认参数)CMD command param1 param2
(shell 格式)
CMD 指令提供容器运行时的默认值,这些默认值可以是一条指令,也可以是一些参数。一个 dockerfile 中可以有多条 CMD 指令,但只有最后一条 CMD 指令有效。CMD 指令与 RUN 指令的命令格式相同,但作用不同:RUN 指令是在镜像的构建阶段用于产生新的镜像;而 CMD 指令则是在容器的启动阶段默认将 CMD 指令作为第一条执行的命令,如果用户在 docker run 时指定了新的命令参数,则会覆盖 CMD 指令中的命令。
# 4.11 ENTRYPOINT
ENTRYPOINT 指令 支持以下两种格式:
ENTRYPOINT ["executable", "param1", "param2"]
(exec 格式,首先)ENTRYPOINT command param1 param2
(shell 格式)
ENTRYPOINT 指令 和 CMD 指令类似,都可以让容器在每次启动时执行相同的命令。但不同的是 CMD 后面可以是参数也可以是命令,而 ENTRYPOINT 只能是命令;另外 docker run 命令提供的运行参数可以覆盖 CMD,但不能覆盖 ENTRYPOINT ,这意味着 ENTRYPOINT 指令上的命令一定会被执行。如下 dockerfile 片段:
ENTRYPOINT ["/bin/echo", "Hello"]
CMD ["world"]
2
当执行 docker run -it image
后,此时输出为 hello world
,而当你执行 docker run -it image spring
,此时 CMD 中的参数会被覆盖,此时输出为hello spring
。
# 五、docker-compose
# 启动 docker
docker-compose up
# 停止 docker
docker-compose down
# 启动 docker 并在后台运行
docker-compose up -d
# 重编译 docker 并运行
docker-compose up --build
2
3
4
5
6
7
8
9
10
11
# 备份数据库
docker exec CONTAINER /usr/bin/mysqldump -u root --password=root DATABASE > backup.sql
# 恢复数据库
cat backup.sql | docker exec -i CONTAINER /usr/bin/mysql -u root --password=root DATABASE
# 六、创建自己的应用镜像
# 6.1 编写自己的应用
写一个小应用操作redis,代码:code/java/docker
# 6.2 Dockerfile
code/java/docker/Dockerfile
FROM openjdk:8-jdk-slim
LABEL maintainer=txpcer
COPY target/*.jar /app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
2
3
4
5
6
# 6.3 构建镜像
docker build -t java-demo:v1.0 -f Dockerfile .
# 6.4 (测试)启动容器
docker run -d p 8080:8080 java-demo:v1.0
# 6.5 推送远程仓库
# 6.6 部署中间件
部署一个Redis+应用,尝试应用操作Redis产生数据
在宿主机创建一个redis的配置文件
vim /data/redis/redis.conf
appendonly yes
requirepass bihell
2
3
启动redis
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
#redis使用自定义配置文件启动
docker run -v /data/redis/redis.conf:/etc/redis/redis.conf \
-v /data/redis/data:/data \
-d --name myredis \
-p 6379:6379 \
redis:latest redis-server /etc/redis/redis.conf
2
3
4
5
6
7
8
9