Docker学习记录

Linux下安装Docker

环境:CentOS7

参考文档:Docker安装文档

1、卸载原有的docker

1
2
3
4
5
6
7
8
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

2、设置yum仓库地址

1
2
3
sudo yum install -y yum-utils

sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

3、安装Docker

1
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

4、启动Docker

1
2
3
4
5
6
# 设置开机自启
sudo systemctl enable docker
# 启动Docker服务
sudo systemctl start docker
# 查看docker版本
docker -v

Docker version 24.0.6, build ed223bc

5、测试Docker

1
sudo docker run hello-world

看到输出结果中包含:Hello from Docker!,则代表测试成功!

6、阿里云镜像加速

进入阿里云搜索:容器镜像服务ACR>镜像工具>镜像加速器

然后按照文档配置即可

1
2
3
4
5
6
7
8
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://你自己的key.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

Docker命令

搜索镜像:docker search 镜像名

1
2
3
4
5
6
7
8
9
10
11
[root@localhost ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 14499 [OK]
mariadb MariaDB Server is a high performing open sou… 5537 [OK]
percona Percona Server is a fork of the MySQL relati… 621 [OK]
phpmyadmin phpMyAdmin - A web interface for MySQL and M… 871 [OK]
bitnami/mysql Bitnami MySQL Docker Image 98 [OK]
circleci/mysql MySQL is a widely used, open-source relation… 29
bitnami/mysqld-exporter 5
ubuntu/mysql MySQL open source fast, stable, multi-thread… 53
cimg/mysql 2

使用命令搜索展示效果不太好,因此更推荐去Docker hub网站上搜索

地址:https://hub-stage.docker.com/search

下载镜像:docker pull 镜像名[:标签]

若没有指定标签,docker默认下载最新版本镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 下载Mysql 8.0.34的镜像
[root@localhost ~]# docker pull mysql:8.0.34
8.0.34: Pulling from library/mysql
5262579e8e45: Pull complete
c6f87bacd0dd: Pull complete
581ee7db3e65: Pull complete
6d5c555a4100: Pull complete
51f4afa7a279: Pull complete
d9e414f0b7c6: Pull complete
aab3a444c469: Pull complete
aab51168fe3a: Pull complete
2a63757e7c9c: Pull complete
830e4b0cc0bc: Pull complete
cc0cd1f61ed7: Pull complete
Digest: sha256:4753043f21f0297253b35a5809a0ec3f12597e8dbeeb709647307edc943ea7b1
Status: Downloaded newer image for mysql:8.0.34
docker.io/library/mysql:8.0.34

列出所有镜像:docker images [选项]

1
2
3
4
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 8.0.34 82ebbd05b8a9 2 months ago 577MB
hello-world latest 9c7a54a9a43c 5 months ago 13.3kB

REPOSITORY:镜像名称
TAG:镜像标签
IMAGE ID:镜像ID(唯一标识)
CREATED:镜像创建时间
SIZE:镜像大小

列出所有的镜像ID

1
2
3
[root@localhost ~]# docker images -q
82ebbd05b8a9
9c7a54a9a43c

查看名为mysql的镜像

1
2
3
[root@localhost ~]# docker images -a --filter=reference=mysql
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 8.0.34 82ebbd05b8a9 2 months ago 577MB

列出正在运行的容器信息:docker ps [选项]

1
2
3
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8bcbd35037c2 nginx "/docker-entrypoint.…" 26 seconds ago Up 23 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp vibrant_colden

CONTAINER ID:容器的ID
IMAGE:镜像
COMMAND:启动时的命令
CREATED:状态
STATUS:运行状态
PORTS:端口信息
NAMES:镜像自动为容器创建的名字,也唯一代表一个容器

列出所有容器,无论是否运行:docker ps -a

列出所有退出状态的容器信息:docker ps -f status=exited

列出所有退出状态的容器ID:docker ps -f status=exited -q

创建并运行容器:docker run [OPTIONS] IMAGE [COMMAND][ARG...]

OPTIONS:选项,需要重点关注 -d、-p、-v、-e、–restart这几个选项
IMAGE:镜像信息,推荐使用 镜像名:TAG的写法,只写镜像名,默认是latest镜像
COMMAND:创建容器后要执行的命令
ARG…:COMMAND命令的参数

运行方式:

  1. 后台运行:docker run -d nginx:latest
  2. 交互式运行:docker run -it nginx:latest bash
  3. 默认运行方式:docker run nginx:latest

run命令详解:

1、-p选项:端口对外发布:docker run -d -p 宿主机端口:容器内端口 镜像名

1
2
[root@localhost ~]# docker run -d -p 8888:80 nginx
29e0de542028874a4ae5e6eacd07f6914d5535303da633a48cb3e5b6c157dfa9

此时可以访问宿主机的8888端口,即可访问到容器内的80端口

2、-v选项:数据卷:docker run -v 宿主机目录:容器目录[:读写权限] 镜像名

读写权限默认是:rw(read-write)可读写,还可以指定为:ro(read-only)只读

-v参数的作用:有时候需要将容器的数据持久化保存,例如MySQL容器,数据会保存在容器内的MySQL对应的文件夹下,若将容器删除,那么之前保存的数据也都会被直接删除,因此我们需要将宿主机的文件挂载到容器内,这样当容器被删除时,宿主机上的数据还是存在的。

将宿主机的/home/nginx/html挂载至容器内的/usr/share/nginx/html:

1
2
[root@localhost ~]# docker run -d -p 8888:80 -v /home/nginx/html:/usr/share/nginx/html nginx
357af0ce617f1ca0ae2328de891e295bb57a6c645ee54bc337b686dd9f52931c

此外,我们还可以使用别名来设置数据卷:docker run -v 数据卷别名:容器目录[:读写权限] 镜像名
这种方式docker会自动帮助我们创建数据卷

1
2
[root@localhost ~]# docker run -d -v nginx_volume:/usr/share/nginx/html nginx
dbe00ea9a07cb6c7b85e18adc3e6c74ce2daafdf5a0b3421377bbc578c74a20c

列出所有数据卷:docker volume ls

1
2
3
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local nginx_volume

查看数据卷详情:docker volume inspect 数据卷名

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost ~]# docker volume inspect nginx_volume
[
{
"CreatedAt": "2023-10-11T23:43:46+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/nginx_volume/_data",
"Name": "nginx_volume",
"Options": null,
"Scope": "local"
}
]

此外,我们还可以手动创建数据卷:docker volume create 数据卷名

1
2
3
4
5
6
[root@localhost ~]# docker volume create my_volume
my_volume
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local my_volume
local nginx_volume

删除数据卷:docker volume rm 数据卷名

1
2
[root@localhost ~]# docker volume rm my_volume
my_volume

3、-e选项:设置环境变量

运行mysql:8.0.34并设置root密码123456

1
2
[root@localhost ~]# docker run -d -p 3306:3306 -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0.34
11ba0689f9c1b7bfc54131ac5ed3f8c0ac24ce680417a9b48409bdf242c26b94

4、–name选项:容器命名

将容器命名为myNginx

1
2
[root@localhost ~]# docker run -d --name myNginx nginx
7bc016df36078cecd577d98377ef31a71a95af74e3233d62e7273a1ae410daad

5、–restart选项:容器退出后重启策略

  • no(默认):容器退出不自动重启
  • always:容器总是在退出后自动重启
  • no-failure[:max-retries]:容器仅在非正常退出时重启,可指定最大重试次数
  • unless-stopped:容器会在退出后自动重启,除非手动停止了容器
1
2
[root@localhost ~]# docker run -d --restart always nginx
caf943e7d4a235c32d113fc9c5e04af8d872ac4176c0e959521fa5ba54221759

删除容器:docker rm [选项] [容器名或ID...]

容器名或ID可以有多个,用空格分开

1
2
[root@localhost ~]# docker rm c69b6855a137
c69b6855a137

强制删除正在运行的容器:docker rm -f 容器ID或容器名

删除所有的容器:docker rm -f $(docker ps -aq)

$() 是Linux中常用的一种命令替换语法,它可以将()中的命令的输出结果作为字符串使用
例如当前所在目录为/home,那么 ls $(pwd) 等价于 ls /home

删除所有非运行状态的容器:docker rm $(docker ps -f status=exited -q)

进入容器执行命令:docker exec [选项] 容器名或ID 命令 [参数...]

1
2
[root@localhost ~]# docker exec df23d0096e17 pwd
/

交互式不退出执行命令:docker exec -it 容器名或ID bash

1
2
3
4
5
6
7
8
[root@localhost ~]# docker exec -it df23d0096e17 bash
root@df23d0096e17:/# pwd
/
root@df23d0096e17:/# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@df23d0096e17:/# exit
exit
[root@localhost ~]#

查看容器日志:docker logs [选项] 容器名或ID

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@localhost ~]# docker logs df23d0096e17
/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
2023/10/11 13:29:04 [notice] 1#1: using the "epoll" event method
2023/10/11 13:29:04 [notice] 1#1: nginx/1.21.5
2023/10/11 13:29:04 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2023/10/11 13:29:04 [notice] 1#1: OS: Linux 3.10.0-1160.95.1.el7.x86_64
2023/10/11 13:29:04 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2023/10/11 13:29:04 [notice] 1#1: start worker processes
2023/10/11 13:29:04 [notice] 1#1: start worker process 31
2023/10/11 13:29:04 [notice] 1#1: start worker process 32

持续显示最新的日志:docker logs -f 容器名或ID

显示最近5行日志:docker logs -n 5 容器名或ID

容器文件拷贝:

将宿主机文件拷贝至容器:docker cp [OPTIONS] SRC_PATH CONTAINER:DEST_PATH

1
2
3
4
[root@localhost ~]# docker cp /home/1.txt df23d0096e17:/home/1.txt
Successfully copied 2.05kB to df23d0096e17:/home/1.txt
[root@localhost ~]# docker exec df23d0096e17 ls /home
1.txt

将容器文件拷贝至宿主机:docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH

1
2
3
4
[root@localhost ~]# docker cp df23d0096e17:/home/1.txt /home/2.txt
Successfully copied 2.05kB to /home/2.txt
[root@localhost ~]# ls /home/
1.txt 2.txt

停止正在运行的容器:docker stop [选项] [容器名或ID...]

1
2
[root@localhost ~]# docker stop df23d0096e17
df23d0096e17

运行停止的容器:docker start [选项] 容器名或ID

1
2
[root@localhost ~]# docker start df23d0096e17
df23d0096e17

查看镜像详细信息:docker image inspect [OPTIONS] 镜像名称...

查看容器详细信息:docker inspect [OPTIONS] 容器名称或Id...

查看容器内进程:docker top 容器名或ID

1
2
3
4
5
[root@localhost ~]# docker top 24ec743ca690
UID PID PPID C STIME TTY TIME CMD
root 11280 11258 0 22:56 ? 00:00:00 nginx: master process nginx -g daemon off;
101 11317 11280 0 22:57 ? 00:00:00 nginx: worker process
101 11318 11280 0 22:57 ? 00:00:00 nginx: worker process

Docker网络

创建网络:docker network create 网络名

1
2
[root@localhost ~]# docker network create my_network_a
1951581e247bb12c61849223ba4c85e075b5d302c9d05d06a72cea1d10d2456a

列出所有网络信息:docker network ls

1
2
3
4
5
6
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
da809e2d48ae bridge bridge local
fc9060b73dce host host local
1951581e247b my_network_a bridge local
82ebb60b619c none null local

加入网络:

  • 创建容器时:docker run --network 网络名 镜像名
  • 创建容器后加入:docker network connect [选项] 网络名 容器名或ID

查看网络详情:docker network inspect 网络名或ID

删除网络:docker network rm 网络名或ID

DockerFile

入门案例:

1、创建文件:touch HelloWorld

2、编写指令:

1
2
FROM centos:7
CMD ["echo","helloworld"]

3、编译镜像:docker build -t hello:1.0 -f HelloWorld .

-t :定义镜像名称和标签
-f :指定DockerFile文件
. :表示在当前目录下查找DockerFile来构建

4、运行镜像:docker run hello:1.0

1
2
[root@localhost ~]# docker run hello:1.0
helloworld

常用命令的作用:

  • FROM:用来定义基础镜像,作用在构建镜像时

  • CMD:用于定义容器运行时的默认命令,可以在使用docker run的时候覆盖掉CMD中定义的命令,作用在容器运行时

    除了CMD ["echo", "helloworld"]这种写法,还可以写成:CMD echo $HOME,这种形式可以解析环境变量;第三种写法:CMD ["sh", "-c", "echo $HOME"]

    一个DOckerFile写多个CMD命令的时候,只有最后一个会起作用。

  • ENV:定义环境变量

    编写dockerfile,定义一个名为CONTENT的环境变量,默认值helloworld,运行容器可指定变量值

    1
    2
    3
    FROM centos:7
    ENV CONTENT="helloworld"
    CMD echo $CONTENT

    docker build -t test:01 -f HelloWorld .

    1
    2
    [root@localhost ~]# docker run -e CONTENT=Hello_JAVA test:01
    Hello_JAVA
  • WORKDIR:设置当前的工作目录,如果该目录不存在,则会自动创建

    类似于Linux的mkdir+cd的组合。

    1
    2
    3
    FROM centos:7
    WORKDIR /a/b/c
    CMD pwd

    docker build -t test:03 -f HelloWorld .

    1
    2
    [root@localhost ~]# docker run test:03
    /a/b/c

    并且WORKDIR可以使用环境变量:

    1
    2
    3
    4
    ENV DIR="/aa/bb"
    WORKDIR $DIR
    # ===等价于===
    WORKDIR /aa/bb
  • RUN:在构建过程中执行指定的命令(区别于CMD,CMD是在镜像运行时执行指定命令)

    需求:定义一个CONTENT环境变量,默认为helloWorld,在镜像/app目录下创建一个myDir目录,并在其中创建content.txt文件,文件内容为CONTENT变量的值,容器启动打印content.txt的内容

    1
    2
    3
    4
    5
    FROM centos:7
    ENV CONTENT="helloWorld"
    WORKDIR /app/myDir
    RUN echo $CONTENT > content.txt
    CMD ["cat", "content.txt"]

    docker build -t test:04 -f HelloWorld .

    1
    2
    [root@localhost ~]# docker run test:04
    helloWorld
  • ADD:将构建上下文中的文件或网络文件添加到镜像中,而且如果文件为压缩包,会自动解压,注意:网络文件并不会自动解压

    将dockerfile所在目录的文件夹myProject中的内容添加到容器内的/app文件夹,并且复制到nginx的html目录并启动

    1
    2
    3
    4
    5
    FROM nginx:1.21.5
    WORKDIR /app
    ADD myProject .
    RUN cp -r * /usr/share/nginx/html
    CMD ["nginx", "-g", "daemon off;"]
  • EXPOSE:声明暴露的容器端口,多个用空格分隔

    1
    2
    3
    4
    5
    6
    FROM nginx:1.21.5
    WORKDIR /app
    ADD myProject .
    RUN cp -r * /usr/share/nginx/html
    EXPOSE 80
    CMD ["nginx", "-g", "daemon off;"]