# 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
1
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 地址[:端口号]/]仓库名[:标签]
1
  • Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub。
  • 仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。

示例:

docker pull ubuntu:18.04
docker pull nginx
1
2

# 2.2 列出镜像

列出已经下载下来的镜像

docker image ls
1

查看镜像、容器、数据卷所占用的空间 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
1

直接列出镜像结果,并且只包含镜像ID和仓库名

$ docker image ls --format "{{.ID}}: {{.Repository}}"
1

查看容器的存储层变动

docker diff
1

查看镜像内的历史记录

docker history nginx:v2
1

# 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)
1
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
1
2

创建镜像

# 注意,最后一个点是 docker 的打包目录, docker 将该目录下所有的文件都打包进镜像。
docker build -t nginx:v3 -f nginx-Dockerfile .
1
2

# 2.5 提交改变

这里提交是在本地新增一个修改了的镜像

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

docker commit -a "leifengyang"  -m "首页变化" 341d81f7504f guignginx:v1.0
1
2
3

# 2.6 镜像传输(镜像备份加载)

# 将镜像保存成压缩包
docker save -o abc.tar guignginx:v1.0

# 别的机器加载这个镜像
docker load -i abc.tar
1
2
3
4
5

# 2.7 推送远程仓库

推送镜像到docker hub;应用市场

docker tag local-image:tagname new-repo:tagname
docker push new-repo:tagname
1
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
1
2
3
4
5
6
7
8
9
10
11
12
13

# 2.x 其他命令

# 查看镜像支持的环境变量
docker run IMAGE env
1
2

# 三、容器相关命令

# 3.1 启动容器

  1. 运行ubuntu容器

有了镜像后,我们就能够以这个镜像为基础启动并运行一个容器。以上面的 ubuntu:18.04 为例,如果我们打算启动里面的 bash 并且进行交互式操作的话,可以执行下面的命令。

$ docker run -it --rm \
    ubuntu:18.04 \
    bash
1
2
3

docker run 就是运行容器的命令,具体格式我们会在 容器 一节进行详细讲解,我们这里简要的说明一下上面用到的参数。

  • -it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 `bash`` 执行一些命令并查看返回结果,因此我们需要交互式终端。
  • --rm:这个参数是说容器退出后随之将其删除。
  • ubuntu:18.04:这是指用 ubuntu:18.04 镜像为基础来启动容器。
  • bash:放在镜像名后的是 命令,这里我们希望有个交互式 Shell,因此用的是 bash
  1. 启动nginx应用容器
# 启动nginx应用容器,并映射88端口,测试的访问
# -d:后台运行
# --restart=always: 开机自启
docker run --name=mynginx   -d  --restart=always -p  88:80   nginx
1
2
3
4

# 3.2 设置应用开机自启

docker update 容器id/名字 --restart=always
1

# 3.3 挂载数据到外部修改

docker run --name=mynginx   \
-d  --restart=always \
-p  88:80 -v /data/html:/usr/share/nginx/html:ro  \
nginx

# 修改页面只需要去 主机的 /data/html
1
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
1
2
3
4
5
6
7
8
9
10

# 3.5 交互方式访问运行中的容器

docker exec -it CONTAINER  bash
1

# 3.6 停止容器

docker stop 容器名
# 停止所有正在运行的容器
docker stop $(docker container ls -q)
1
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)
1
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 往往会让容器内应用进程终止,进而会终止容器。
1
2
3
4
5

# 3.9 删除网络

docker network ls
docker network rm my_network
1
2

# 3.10 查看容器日志

docker logs 容器名/id 
1

# 3.11 把容器指定位置的东西复制

#把容器指定位置的东西复制出来 
docker cp 5eff66eec7e1:/etc/nginx/nginx.conf  /data/conf/nginx.conf
#把外面的内容复制到容器里面
docker cp  /data/conf/nginx.conf  5eff66eec7e1:/etc/nginx/nginx.conf
1
2
3
4

# 3.12 重启容器

docker restart 容器名
1

# 四、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
1
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"]
1
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 
1
2
3
4
5
6
7
8
9
10
11

# 备份数据库

docker exec CONTAINER /usr/bin/mysqldump -u root --password=root DATABASE > backup.sql
1

# 恢复数据库

cat backup.sql | docker exec -i CONTAINER /usr/bin/mysql -u root --password=root DATABASE
1

# 六、创建自己的应用镜像

# 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"]
1
2
3
4
5
6

# 6.3 构建镜像

docker build -t java-demo:v1.0 -f Dockerfile .
1

# 6.4 (测试)启动容器

docker run -d p 8080:8080 java-demo:v1.0
1

# 6.5 推送远程仓库

# 6.6 部署中间件

部署一个Redis+应用,尝试应用操作Redis产生数据

在宿主机创建一个redis的配置文件

vim /data/redis/redis.conf
appendonly yes
requirepass bihell
1
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
1
2
3
4
5
6
7
8
9
更新时间: 12/7/2022, 1:57:26 PM