docker常用命令、实操(包含实用配置)

容器云

docker,大数据,Linux,python

docker常用命令、实操(包含实用配置)

前言

镜像就像操作系统。容器就像装了操作系统的虚拟机。(这种说法不完全正确,容器和虚拟机不一样,但可以这么理解。)

  • 先下载镜像(操作系统)
  • 再下载容器(虚拟机)
  • 再给容器(虚拟机)装上镜像(操作系统)
    故下面知识总结顺序:镜像 -> 容器。

1. 镜像

1)查找镜像

docker search centos
docker search ubuntu

2)拉取(下载)镜像镜像

docker pull ubuntu:16.04
docker pull ubuntu   # 不加版本号默认下载最新版
docker pull centos:7
docker pull centos   # 不加版本号默认下载最新版

附:查看docker支持的镜像网站:

  • Centos: https://hub.docker.com/_/centos?tab=tags&page=1
  • Ubuntu: https://hub.docker.com/_/ubuntu?tab=tags

3)查看本地所有镜像信息

docker images

在这里插入图片描述

4)为镜像打标签(起别名)

比如我们将上面下载的最新的centos镜像标注以下,以方面区分。
在这里插入图片描述以上图为例,将镜像名为centos、版本号 latest的镜像起别名为:local_centos、版本号为v1:

# 法1: repository名法。(注意 repository名 可能会有重名情况)
docker tag centos local_centos:v1
# 法2: image法(iamge_id 除了别名以外具有唯一性)
docker tag 5d0da3dc9764 local_centos:v1
# 法3(推荐):repository名+TAG法。(具有唯一性)
docker tag centos:latest local_centos:v1

再次输入 docker images 查看:
在这里插入图片描述上面推荐使用法3,方便快捷,可以按Tab键自动生成补全信息;而法2虽然具有唯一性,但不会自动补全,反而输入IMAGE_ID很麻烦;法1不具备唯一性,当有重名的时候不适用,如下,我们又下载了一个centos7的镜像时:
在这里插入图片描述这里centos重名,法1不再适用。只能选具备唯一性的法2或法3。

5)保存(打包)镜像

在这里插入图片描述

# 法1:打包 iamge_id 为 eeb6ee3f44bd 的镜像,保存到 /opt/centos7.tar.gz
docker save -o /opt/centos7.tar.gz eeb6ee3f44bd
# 法2:打包 repository名 为 centos、版本号为7的镜像。(注意 repository名 可能会有重名)
docker save -o /opt/centos7.tar.gz centos:7
# 打包 repository名为 local_centos镜像。(注意 repository名 可能会有重名)
docker save -o /opt/local_centos.tar.gz local_centos

注:参数 -ooutput
提示:如果为非root用户,操作 /opt目录 需要sudo权限。

6)删除镜像

在这里插入图片描述

(1)删除centos7的镜像:
# 法1(image_id法)
docker rmi eeb6ee3f44bd
# 法2(repository + TAG 法)
docker rmi centos:7

:参数 rmi 即 rm image

(2)删除最新版的centos的镜像:

最新版centos镜像有两个:centos(latest)和它的别名 local_centos(v1)
如果想这两个都删除,有两种方式:

方式一:一个个删
docker rmi centos:latest
docker rmi local_centos:v1
方式二:强制一次性删

这两个image_id相同的(为5d0da3dc9764)镜像,当输入
docker rmi 5d0da3dc9764 会报错:
Error response from daemon: conflict: unable to delete 5d0da3dc9764 (must be forced) - image is referenced in multiple repositories
需要加上强制参数-f

docker rmi -f 5d0da3dc9764

:参数 -f 即force,类似的还有 rm -rf

7)载入(还原)镜像

如将之前备份的 /opt/centos7.tar.gz 镜像还原。如果非root用户,操作opt目录需要sudo权限

docker load -i /opt/centos7.tar.gz

:参数 -iinput 入的意思。
与前面的结合记忆:

  • docker save -o 备份
  • docker load -i 载入

2. 容器

容器就像装了操作系统的虚拟机。

1)查看本地容器信息

# (1)查看本地正在运行的容器信息
docker ps

#(2)查看本地的所有容器信息
docker ps -a

目前没有容器,结果为空:
在这里插入图片描述

2)创建、启动、进入容器

例:创建一个名为mycontainer的容器,系统为本地存在的(之前pull过的)镜像centos7。创建后启动、再进入该容器(虚拟机)

法(1):
# 创建一个名为mycontainer的容器,系统为本地存在的(之前pull过的)镜像centos7
docker create -it --name mycontainer docker.io/centos:7 /bin/bash
# 或 docker create -it --name mycontainer centos:7 /bin/bash

# 启动容器。容器名为mycontainer
docker start mycontainer

# 进入该容器
docker exec -it mycontainer /bin/bash

在这里插入图片描述
讲解

  • i)第一句 docker create -it --name mycontainer docker.io/centos:7 /bin/bash
    -i : input。表示将标准输入设置为始终打开状态。
    -t : terminal。表示附加一个伪终端。
    这里,-i-t可以合并在一起写成-it
    --name mycontainer : 表示添加一个名为mycontainer(自定义)的容器。
    docker.io/centos:7 : 表示在 本地找寻pull好的 centos7镜像(前面 docker pull centos:7)。 若写成 centos,则表示默认寻找lastest版本(最新版)的镜像,若之前没有拉取最新版镜像(docker pull centos),则会报错找不到。docker.io表示Ubuntu发行版。也可省略docker.io/。其中,docker-ce 是 docker 官方维护的,docker.io 是 Debian 团队维护的。
    bin/bash : 表示之后启动进入容器后自动运行bash(打开终端)。
    如果少了这些参数,后面的两步是进入不了该容器的。
  • ii)第二句docker start mycontainer
    这句是以容器名(NAMES)为标识启动该容器,也可以容器ID(CONTAINER_ID)为表示启动该容器。
# 启动容器。容器id为9842e2c8900f
docker start 9842e2c8900f

但我更喜欢以容器名启动,因为输入ID太麻烦。(启动容器这句话有时不支持输入Tab自动生成)

  • iii)第三句docker exec -it mycontainer /bin/bash
    同理也可用ID进入容器
docker exec -it 9842e2c8900f /bin/bash

但因为输入ID太麻烦,还是选择以容器名启动更方便(而且,进入容器这句话支持输入Tab自动生成)
进入容器后退出容器要用 exit 命令(ctrl + c 不管用的),如下:
在这里插入图片描述另外,再说一下各个参数:
/bin/bash : 同样表示启动进入容器后自动运行bash(打开终端)。如果不加就会报错,错误示例如下图:
在这里插入图片描述
-i : input。表示将标准输入设置为始终打开状态。如果不加 -i 参数,虽然能进入容器,但输入任何命令都不管用!(由于标准输入没有被打开所以不会被识别),错误示例如下图:
在这里插入图片描述
-t : terminal。表示附加一个伪终端。如果不加这个参数会进不去该容器,一直卡顿,错误示例如下图:
在这里插入图片描述

法(2)【推荐】:

创建容器的同时直接启动并进入该容器,直接将上面创建容器的语句 create 命令改成 run 即可!

docker run -it --name mycontainer docker.io/centos:7 /bin/bash

3)退出容器

进入容器后退出容器要用 exit 命令(ctrl + c 不管用的),如下:
在这里插入图片描述

4)停止容器

# 停止容器。容器名为mycontainer
docker stop mycontainer

# 同理,也可使用容器ID停止。
docker stop 9842e2c8900f

5)重启容器

# 重启容器。容器名为mycontainer
docker restart mycontainer

# 同理,也可使用容器ID重启。
docker restart 9842e2c8900f

6)删除容器

# 删除容器。容器名为mycontainer
docker rm mycontainer

# 同理,也可使用容器ID删除。
docker rm 9842e2c8900f

如果容器正在运行,需先将容器stop后才能删除!或者也可使用 -f 参数强制删除!

# 强制删除正在运行的容器。容器名为mycontainer
docker rm -f mycontainer

# 同理,也可使用容器ID强制删除。
docker rm -f 9842e2c8900f

7)批量操作所有容器

我们创建三个容器:

# 创建3个容器,容器名为mycontainer, test, test2
docker create -it --name mycontainer docker.io/centos:7 /bin/bash
docker create -it --name test docker.io/centos:7 /bin/bash
docker create -it --name test2 docker.io/centos:7 /bin/bash

创建后使用docker ps -a查看一下:
在这里插入图片描述
要想批量操作所有容器,我们首先要获取到所有容器的ID或者name。前面讲过查看本地的所有容器信息的命令是

docker ps -a

如果只显示容器ID,可以再加个-q参数,即:

docker ps -a -q

结果如下:
在这里插入图片描述所以,接下来所有批量操作命令,都可以借助于将docker ps -a -q 当成变量,写成:$(docker ps -a -q)。具体如下:

(1)批量启动所有容器
# 批量启动所有容器
docker start $(docker ps -a -q)

已批量开启所有容器,即容器ID为c8a3f3e88301, 76077156505d, 9842e2c8900f的三个容器,如下:
在这里插入图片描述

(2)批量停止所有容器
# 批量停止所有容器
docker stop $(docker ps -a -q)

已批量停止所有容器,即容器ID为c8a3f3e88301, 76077156505d, 9842e2c8900f的三个容器,如下:
在这里插入图片描述

(3)批量重启所有容器
# 批量重启所有容器
docker restart $(docker ps -a -q)

已批量重启所有容器,即容器ID为c8a3f3e88301, 76077156505d, 9842e2c8900f的三个容器,如下:
在这里插入图片描述

(3)批量删除所有容器

正在运行的容器要先stop才能删除,或者用-f参数强制删除。

# 强制删除所有容器(包括正在运行的)
docker rm -f $(docker ps -a -q)

已批量强制删除所有容器,即容器ID为c8a3f3e88301, 76077156505d, 9842e2c8900f的三个容器,如下:
在这里插入图片描述

8)查看容器信息

docker inspect 容器名

docker inspect myubuntu20.04Container

信息很长,部分截图如下:
在这里插入图片描述

9)挂载卷

(1)挂载目录

可以在创建容器的时候设置挂载目录。

(1.1)给容器设置一个单独的挂载目录

:创建容器名为my_volumes1,创建后在该容器内自动生成目录 /volumes_usb 作为挂载卷。

docker run -it --name my_volumes1 -v /volumes_usb ubuntu:20.04 /bin/bash

结果:
在这里插入图片描述可看到执行上面命令后,新容器中已自动生存 /volumes_usb 目录。

(1.2)将主机的一个目录设置为容器的挂载目录

:创建容器名为my_volumes2,并将主机的 /home/hadoop/mydocker/mnt 目录挂载到新容器my_volumes2中自动生成的 /volumes_usb目录下。

 docker run -it --name my_volumes2 -v /home/hadoop/mydocker/mnt/:/volumes_usb ubuntu:20.04 /bin/bash
 ############  docker语法习惯,永远记住:冒号左边是主机,右边是容器!   #############

说明:创建后在该容器内自动生成目录 /volumes_usb 作为挂载卷,并将主机的 /home/hadoop/mydocker/mnt 目录挂载到新容器my_volumes2中的 /volumes_usb目录下。
注:上面的语句执行后,既会在主机中自动生成/home/hadoop/mydocker/mnt 文件夹(如果没有),也会在新容器my_volumes2中自动生成/volumes_usb文件夹。即:在 /home/hadoop/mydocker/ 目录下也可以不事先新建好 mnt/ 文件夹,因为执行上面的命令会自动生成该目录。
结果:
在这里插入图片描述在这里插入图片描述
可看到执行命令后,新容器中已自动生存 /volumes_usb 目录,主机中有/home/hadoop/mydocker/mnt 目录。

(2)挂载容器

在生产环境中,有时候容器间需要共享数据,这时就需要先创建一个已经挂载了卷的容器,然后把这个容器作为专门的数据卷容器提供给其他容器挂载。
挂载容器需要 --volumes-from 参数。
:新建my_volumes3容器,并将前面创建好的my_volumes1容器的卷(/volumes_usb目录)挂载到my_volumes3容器上。

docker run -it --name my_volumes3 --volumes-from my_volumes1 ubuntu:20.04 /bin/bash

结果:
在这里插入图片描述
可以看到新容器my_volumes3已挂载上my_volumes1容器的卷(/volumes_usb目录)。
测试:
我们再新开一个终端,进入my_volumes1容器,在其挂载卷/volumes_usb目录下新建一个文件1.txt,如下:
在这里插入图片描述然后再回到新容器my_volumes3中查看其挂载的/volumes_usb目录,可已看新文件1.txt,如下:
在这里插入图片描述

10)连接容器

容器之间是相互隔离的,可以使用link 命令,在两个容器之间建立一条信道,使容器内的应用实现通信。验证是否通信用ping命令即可!
下面以centos为例,因为docker pull的centos自带ping命令,而ubuntu没有自带需要下载安装。

# 创建一个名为server的容器
docker run -it --name server centos:7 /bin/bash

再开一个终端

# 创建一个名为client的容器,并连接容器server。(注意容器server要保证启动状态,才能连接上)
docker run -it --name client --link server:server centos:7 /bin/bash

注:如果不想再开一个终端,可以exit退出server容器后,再启动server容器!如下:
在这里插入图片描述通信验证
在client容器中,终端输入

ping server

能ping通即表示容器client成功连通上容器server!全部步骤如下:
在这里插入图片描述注意:
link这种连通方式是单向的,而非双向,即client能连接上server,但server却不能连接上client。试着在server容器去ping client容器会发现ping不通、找不到。如下图:
在这里插入图片描述
如果需要在server容器中连接client容器,就需要在sever容器端作额外的配置,然而,在生产环境中,由于承载不同服务的容器很多,使用link参数构建网络就不可取了,这会导致配置增多,加大运维的难度。怎么办?下面容器网络解决。

11)容器网络

(1)3种网桥

容器网络network可实现网络的互通互联。
docker 自带3种网桥,输入

docker network ls

可看到,如下:
在这里插入图片描述

  • bridge:是docker默认的网络,通过这个默认的birdge,容器可以通过主机网卡访问外网。
  • host:和宿主机共享网络,容器和主机之间没有隔离网络。
  • none:表示没有网络,不能联网。
(2)自定义网桥

自定义网桥后,再将需要互通的容器添加到自定义的网桥中,便可以实现容器间的互通了。
为什么自定义网桥呢?因为自定义网桥比默认的网桥隔离性好,而且方便。因此在设计容器网络尤其网络互通时候应优先选择自定义网桥。

# 创建一个自定义的网桥,新网桥名为customize_bridge
docker network create -d bridge customize_bridge

验证: 此时再次输入 docker network ls ,可以看到多了自定义的网桥customize_bridge,网桥驱动模式为默认的bridge模式, 如下:
在这里插入图片描述

(3)将需要互通(互相通信)的容器添加到自定义网桥中
(3.1)将已存在的容器添加到自定义网桥customize_bridge中

前面已经创建过client和server容器。以client容器为例:

# 将已存在的容器client,网络连接使用customize_bridge网桥网络。
docker network connect customize_bridge client
(3.2)新创建一个容器,并将其添加到自定义网桥customize_bridge中
# 新建容器client1,采用centos7镜像,使用customize_bridge网桥网络。
docker run -it --name client1 --network customize_bridge centos:7 /bin/bash
(3.3)验证测试:
  • (i) 保证client和client1两个容器都已启动。没有启动的话输入:
docker start client
docker start client1
  • (ii) 再输入
docker inspect customize_bridge

可以看到client容器和client1容器都在customize_bridge网桥网络内,如下图:
在这里插入图片描述注:如果容器没启动用这个命令是看不到的。

  • (iii) 新开两个终端,分别进入client容器和client容器,互相ping对方,可以看到能互相ping通,即:添加到自定义的customize_bridge网桥的两个容器client和client1已成功互通!!!
    在这里插入图片描述
    在这里插入图片描述

12)获取镜像总结

(1)pull 拉取镜像 ------ 常用
docker pull ubuntu:20.04
(2)commit 提交镜像(将容器打包后提交成镜像) ------ 重点!常用
将已有的容器mycontainer打包提交成镜像p1_image:v1。
docker commit mycontainer p1_image:v1

将镜像保存成文件 p1_image_v1.tgz
docker save -o p1_image_v1.tgz p1_image:v1
(2)load 载入镜像(还原。不可自定义新镜像名和版本)
docker load -i /路径/p1_image_v1.tgz
docker load -i /home/hadoop/mydocker/images/ubuntu20.04.tar.gz
# -i 表 input
(3)import 导入镜像(可自定义新镜像名和版本)
docker import /路径/p1_image_v1.tgz p1_image:v1.0
docker import /home/hadoop/mydocker/images/ubuntu20.04.tar.gz ubuntu:v2

与load不同的是,import可以自定义导入后的镜像名和版本,而load载入是还原的意思,不能自定义,即原来备份的ubuntu20.04.tar.gz 中是什么镜像名和版本,经load载入还原后就还是什么镜像名和版本。

(4)Dockerfile创建镜像

Dockerfile创建镜像。后面第3节讲解。

13)创建容器并在容器中装上镜像的几种方式总结(类似:创建虚拟机后再装上系统)

假设本地有镜像ubuntu:20.04。(通过dokcer images查看后)

(1)run 创建容器并启动执行
docker run -it --name mycontainer ubuntu:20.04 /bin/bash
(2)create创建容器,commit提交给容器要用的镜像
docker create -it mycontainer
docker commit mycontainer ubuntu:20.04

3. Dockerfile创建镜像

先来干货,直接上个例子!

例:

通过本地下载好的基础镜像 ubuntu:20.04,在该镜像中安装 jdk 和 tomcat 以后将其制作为一个新的镜像 myubuntu:20.04。制作后将镜像(类似系统)放在容器(类似虚拟机)中,容器名为 myubuntu20.04Container。
假设电脑用户名为hadoop。docker中存在镜像 ubuntu:20.04,如下图:
在这里插入图片描述

1)步骤
(i)准备软件 jdk 和 tomcat

先在主目录即/home/hadoop 下新建文件夹 bak,在 bak文件夹下存放网上下载好的软件 jdk-8u271-linux-x64.tar.gzapache-tomcat-9.0.59.tar.gz ,其中:

  • apache-tomcat-9.0.59.tar.gz 解压后文件夹名为:apache-tomcat-9.0.59
  • jdk-8u271-linux-x64.tar.gz 解压后文件夹名为:jdk1.8.0_271

如下图:
在这里插入图片描述

(ii)准备Dockerfile文件

再在主目录即/home/hadoop 下新建文件夹 mydocker,在 mydocker文件夹下新建文件Dockerfile,文件Dockerfile内容如下:

# 基础镜像
FROM ubuntu:20.04

# 维护者信息
LABEL maintainer="111@qq.com"
# 下面这种写法官方不建议了
# MAINTAINER my first image 111@qq.com

# 设置工作目录
WORKDIR /mnt

# 新镜像构建成功以后创建指定目录
RUN mkdir -p /usr/local/java && mkdir -p /opt/tomcat

# 拷贝文件到镜像中并解压
ADD jdk-8u271-linux-x64.tar.gz /usr/local/java
ADD apache-tomcat-9.0.59.tar.gz /opt/tomcat

# 暴露容器运行时的 8080 监听端口给外部
EXPOSE 8080

# 设置容器内 JAVA_HOME 环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_271/
ENV PATH $PATH:$JAVA_HOME/bin

# 启动容器时启动tomcat并查看tomcat日志信息
ENTRYPOINT /opt/tomcat/apache-tomcat-9.0.59/bin/startup.sh && tail -f /opt/tomcat/apache-tomcat-9.0.59/logs/catalina.out
(iii)执行Dockerfile文件,在ubuntu:20.04镜像中安装 jdk 和 tomcat 后,并将其制作为一个新的镜像 myubuntu:20.04

输入

docker build -f Dockerfile -t myubuntu:20.04 /home/hadoop/bak

成功结果如下图:
在这里插入图片描述此时输入 docker images 可以看到新建的镜像 myubuntu:20.04,如下图:
在这里插入图片描述

(iv)创建新容器myubuntu20.04Container,并将新镜像 myubuntu:20.04放在新容器myubuntu20.04Container中,通信端口:8080,再启动容器。(可将容器看成虚拟机)

可以用下面一句话完成:

docker run -it --name myubuntu20.04Container -p 8080:8080 myubuntu:20.04

结果如下图,可看到启动容器时tomcat已自动启动(正如Dockerfile设置的那样):
在这里插入图片描述此时输入 docker ps 可看到正在运行的容器myubuntu20.04Container,其镜像用的是 myubuntu:20.04,如下:
在这里插入图片描述

(v)使用

a)以命令终端打开进入装了新镜像的新容器,输入

docker exec -it myubuntu20.04Container /bin/bash

可看到进入后默认的工作目录是/mnt(在Dockerfile定义),jdk已安装在/usr/local 下,tomcat已安装在/opt下,如下图:
在这里插入图片描述
b)在主机输入ifconfig,可以看到有一个名为docker0的网卡,ip地址为172.17.0.1,即是新容器镜像的地址(类似新虚拟机地址)。如下:
在这里插入图片描述
在主机中访问这个地址的8080端口,浏览器输入172.17.0.1:8080 即可访问我们刚刚新建的新镜像容器的tomcat了,如下图:
在这里插入图片描述
附:(这个了解即可)也可不用docker网卡地址,也可用主机网卡地址,ifconfig可以看到(不是localhost)。

2)步骤讲解

下面结合Dockerfile常用指令知识,对上面的步骤进行讲解。

(1)Dockerfile 常用指令讲解:
  • FROM
    语法:FROM <image>:<tag>
    功能:指明构建的新镜像是来自于哪个基础镜像(已经pull到本地的),如果没有选择 tag,那么默认值为 latest。
    如果不以任何镜像为基础,那么写法为:FROM scratch。官方说明:scratch 镜像是一个空镜像,可以用于构建 busybox 等超小镜像,可以说是真正的从零开始构建属于自己的镜像。
    例如:
# 基础镜像
FROM ubuntu:20.04
  • MAINTAINER(deprecated)
    语法:MAINTAINER <name>
    功能:指明镜像维护者及其联系方式(一般是邮箱地址)。官方说明已过时,推荐使用下面的 LABEL写法。
    例如:
# 维护者信息(不推荐,已过时)
MAINTAINER Ace 111@qq.com
  • LABEL
    语法:LABEL <key>=<value> <key>=<value> <key>=<value> ...
    功能:为镜像指定标签。也可以使用 LABEL 来指定镜像作者。
    例如:
# 维护者信息(不推荐,已过时)
LABEL maintainer="111@qq.com"
  • RUN
    语法:RUN <command>
    功能:构建镜像时运行的 Shell 命令。
    例如:
# 新镜像构建成功以后创建指定目录
RUN mkdir -p /usr/local/java && mkdir -p /opt/tomcat
  • ADD
    语法:ADD <src>... <dest>
    功能:拷贝文件或目录到镜像中,若拷贝的是压缩包的话会自动解压。src 可以是一个本地文件或者是一个本地压缩文件,压缩文件会自动解压;还可以是一个 url,如果把 src 写成一个 url,那么 ADD 就类似于 wget 命令,然后自动下载和解压。
    例如:
# 拷贝文件到镜像中并解压
ADD jdk-8u271-linux-x64.tar.gz /usr/local/java
  • COPY
    语法:COPY <src>... <dest>
    功能:拷贝文件或目录到镜像中。用法同 ADD,只是不支持自动下载和解压。
    例如:
# 拷贝文件到镜像中(不解压)
COPY jdk-8u271-linux-x64.tar.gz /usr/local/java
  • EXPOSE
    语法:EXPOSE <port> [<port>/<protocol>...]
    功能:暴露容器运行时的监听端口给外部,可以指定端口是监听 TCP 还是 UDP,如果未指定协议,则默认为 TCP。
    在容器启动的时候加上 -P 参数,即可使得容器与宿主机的端口有了映射关系。
    例如:
# 暴露容器运行时的 8080 监听端口给外部
EXPOSE 8080

如果想暴露多个端口的话:

# 暴露容器运行时的 80,443,和 8080 监听端口给外部
EXPOSE 80 443 8080/tcp
  • ENV
    语法:ENV 添加单个,ENV = … 添加多个。
    功能:设置容器内环境变量。
    例如:
# 设置容器内 JAVA_HOME 环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_271/
ENV PATH $PATH:$JAVA_HOME/bin
  • CMD
    语法:
    CMD ["executable","param1","param2"],如:CMD ["/usr/local/tomcat/bin/catalina.sh", "start"]
    CMD ["param1","param2"],如:CMD [ "echo", "$JAVA_HOME" ]
    CMD command param1 param2,如:CMD echo $JAVA_HOME
    功能:启动容器时执行的 Shell 命令。在 Dockerfile 中只能有一条 CMD 指令。如果设置了多条 CMD,只有最后一条 CMD 会生效。
    如果创建容器的时候指定了命令,则 CMD 命令会被替代。假如镜像叫 myubuntu:20.04,创建容器时命令是:docker run -it --name myubuntu20.04Container myubuntu:20.04 echo "helloworld" 或者 docker run -it --name myubuntu20.04Container myubuntu:20.04 /bin/bash,就不会输出 $JAVA_HOME 的环境变量信息了,因为 CMD 命令被 echo "helloworld"/bin/bash 命令覆盖了。
    例如:
# 启动容器时输出 $JAVA_HOME 信息(但是会被docker run启动命令行指定参数所覆盖)
CMD ehco $JAVA_HOME
  • ENTRYPOINT
    语法:

    ENTRYPOINT ["executable", "param1", "param2"],如:ENTRYPOINT ["/usr/local/tomcat/bin/catalina.sh", "start"]
    ENTRYPOINT command param1 param2,如:ENTRYPOINT ehco $JAVA_HOME
    功能:启动容器时执行的 Shell 命令,同 CMD 类似,不会被 docker run 命令行指定的参数所覆盖。在 Dockerfile 中只能有一条 ENTRYPOINT 指令。如果设置了多条 ENTRYPOINT,只有最后一条 ENTRYPOINT 会生效。
    例如:

# 启动容器时输出 $JAVA_HOME 信息(不会被docker run启动命令行指定参数所覆盖)
ENTRYPOINT ehco $JAVA_HOME
# 启动容器时启动tomcat并查看tomcat日志信息
ENTRYPOINT /opt/tomcat/apache-tomcat-9.0.59/bin/startup.sh && tail -f /opt/tomcat/apache-tomcat-9.0.59/logs/catalina.out
	注意:
		如果在 Dockerfile 中同时写了 ENTRYPOINT 和 CMD,
		并且 CMD 指令不是一个完整的可执行命令,
		那么 CMD 指定的内容将会作为 ENTRYPOINT 的参数;
		如果在 Dockerfile 中同时写了 ENTRYPOINT 和 CMD,
		并且 CMD 是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效
  • WORKDIR
    语法:WORKDIR 目录名
    功能:为 RUN、CMD、ENTRYPOINT 以及 COPY 和 ADD 设置工作目录,即打开终端后进入的目录。这样当执行命令的时候就会自动在这里执行了。
    例如:
WORKDIR /mnt

打开终端后自动在/mnt目录下
在这里插入图片描述若工作目录放在/usr/local下,再用RUN、CMD、 COPY 和 ADD 等命令就默认在/usr/local下使用了,方便的多了:

WORKDIR /usr/local
  • VOLUME
    语法:VOLUME ["目录名"]
    功能:指定容器挂载点到宿主机自动生成的目录或其他容器。一般的使用场景为需要持久化存储数据时。
    但这个参数一般不会在 Dockerfile 中用到,更常见的还是在 docker run 的时候通过 -v 指定数据卷。
    例如:
# 容器的 /var/lib/mysql 目录会在运行时自动挂载为匿名卷,匿名卷在宿主机的 /var/lib/docker/volumes 目录下
VOLUME ["/var/lib/mysql"]
(2)使用Dockerfile构建镜像命令讲解:
docker build -f Dockerfile -t myubuntu:20.04 /home/hadoop/bak
  • docker build 构建
  • -f Dockerfile 中的 -f 是 file的意思,-f后面接Dockfile的路径,来识别 Dockerfile。当前目录即 ./Dockerfile
  • -t是terminal的意思,表示附加一个伪终端。常和-i(表标准输入设置为始终打开状态)一起写成-it
  • myubuntu:20.04 是使用Dockerfile创建镜像后的新镜像名。
  • /home/hadoop/bak 表构建新镜像时在本机该目录下找软件(像下载好的jdk,tomcat软件事先放在这里),构建镜像时该路径下所有文件都打包上传给Docker引擎。这个有点类似我们平时我们用的主机和虚拟机之间的共享目录。
    重点:这里有个知识点,如果Dockerfile和jdk,tomcat这些软件放在同一个目录下了,比如都放在/home/hadoop/mydocker下了,如下:
    在这里插入图片描述那么我们构建镜像的时候可以有个简略的写法,可以不用再写绝对路径了,而用 . 来代替,表当前路径,类似于linux的 ./ 。利用Dockerfile构建新镜像的命令可以间写成:
# 注意:末尾有个点 "."
docker build -f Dockerfile -t myubuntu:20.04 .

另外,因为Dockerfile是当前目录的, Dockerfile也可以省略,会自动搜索当前目录下的Dockerfile文件。

# 注意:末尾有个点 "."
docer build -t myubuntu:20.04 .
(3)创建新容器myubuntu20.04Container,并将新镜像 myubuntu:20.04放在新容器myubuntu20.04Container中,通信端口:8080,再启动容器。(可将容器看成虚拟机)命令讲解:
docker run -it --name myubuntu20.04Container -p 8080:8080 myubuntu:20.04
  • docker run:创建容器后立即运行并进入容器。
  • -it-i 即input,表将标准输入设置为始终打开状态。-t 即terminal,表附加一个伪终端,-i-t可以合并在一起写。
  • --name myubuntu20.04Container :新容器名
  • -p 8080:8080:暴露的端口。和主机交互。创建时即要添加容器和主机的端口映射。
    这个例子中,如果想用8181,需要改3处地方:一个是Dokcerfile中定义,一个是tomcat软件包中的xml文件端口(tomcat默认8080端口,否则启动不了tomcat),一个是这个命令。
  • myubuntu:20.04: 前面创建的新镜像名
3)实战常用习惯总结(干货)

假设电脑用户名为hadoop
(1)在主目录即/home/hadoop 下新建文件夹 mydocker,在 mydocker文件夹下新建文件Dockerfile
(2)在网上下载好软件 jdk-8u271-linux-x64.tar.gzapache-tomcat-9.0.59.tar.gz ,并放在mydocker文件夹下,其中:

  • apache-tomcat-9.0.59.tar.gz 解压后文件夹名为:apache-tomcat-9.0.59
  • jdk-8u271-linux-x64.tar.gz 解压后文件夹名为:jdk1.8.0_271

(3)Dockerfile 文件内容:

# 基础镜像
FROM ubuntu:20.04

# 维护者信息
LABEL maintainer="111@qq.com"
# 下面这种写法官方不建议了
# MAINTAINER my first image 111@qq.com

# 设置工作目录
WORKDIR /usr/local

# 新镜像构建成功以后创建指定目录
RUN mkdir -p /usr/local/java

# 拷贝文件添加到镜像中并解压
ADD jdk-8u271-linux-x64.tar.gz /usr/local/java
ADD apache-tomcat-9.0.59.tar.gz /opt/

# 重命名文件夹
RUN mv /opt/apache-tomcat-9.0.59 /opt/tomcat

# 暴露容器运行时的 8080 监听端口给外部
EXPOSE 8080

# 设置容器内 JAVA_HOME 环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_271/
ENV PATH $PATH:$JAVA_HOME/bin

# 启动容器时启动tomcat并查看tomcat日志信息
ENTRYPOINT /opt/tomcat/bin/startup.sh && tail -f /opt/tomcat/logs/catalina.out

终端执行

# 创建镜像myubuntu:20.04。注意!末尾有个点 “.”
# docker build -f Dockerfile -t myubuntu:20.04 .
# 上面的Dockerfile也可省略(默认自动搜索当前目录下的Dockerfile文件),如下:
docker build -t myubuntu:20.04 .
# 创建并启动进入容器myubuntu20.04Container。
docker run -it --name myubuntu20.04Container -p 8080:8080 myubuntu:20.04

另开一个终端

# 查看所有的镜像。可以看到新镜像myubuntu:20.04
docker images
# 查看所有的容器。可以看到新容器myubuntu20.04Container
docker ps -a
# 查看正在运行的容器。可以看到新容器myubuntu20.04Container已经开启
docker ps
# 关闭容器
docker stop myubuntu20.04Container
# 再次启动容器
docker start myubuntu20.04Container

# 以命令行终端模式进入容器。进入后可以用 exit 命令退出。
docker exec -it myubuntu20.04Container /bin/bash


因为Dockerfile设置了工作目录,所以Dockerfile如创建文件夹等之类的操作可以不写绝对路径,使用相对路径。Dockerfile再次精简后的写法如下:

# 基础镜像
FROM ubuntu:20.04

# 维护者信息
LABEL maintainer="111@qq.com"
# 下面这种写法官方不建议了
# MAINTAINER my first image 111@qq.com

# 设置工作目录
WORKDIR /usr/local

# 新镜像构建成功以后创建指定目录
RUN mkdir java

# 拷贝文件到镜像中并解压
ADD jdk-8u271-linux-x64.tar.gz ./java
ADD apache-tomcat-9.0.59.tar.gz /opt/

RUN mv /opt/apache-tomcat-9.0.59 /opt/tomcat

# 暴露容器运行时的 8080 监听端口给外部
EXPOSE 8080

# 设置容器内 JAVA_HOME 环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_271/
ENV PATH $PATH:$JAVA_HOME/bin

# 启动容器时启动tomcat并查看tomcat日志信息
ENTRYPOINT /opt/tomcat/bin/startup.sh && tail -f /opt/tomcat/logs/catalina.out

4. 容器镜像配置国内镜像源 – 解决docker安装ubuntu精简版镜像apt install找不到包

我们用docker pull下的镜像都是精简版的,装在容器中,一些基本的命令如vim都没有。而用 apt install vim 又提示找不到。这个问题可以通过给容器内镜像系统配置国内镜像源来解决。

步骤

进入docker 装了ubuntu20.04系统的容器后,改/etc/apt/sources.list文件,但由于没有vimgedit命令,所以我们可以有两种方式:

  • 一是可以借助于echo命令来修改文件内容。
  • 二是在docker容器系统中设置挂载卷,在主机编辑好文件在复制过去。
    采用第一种方式更方便,输入如下命令:
# 1. 先备份
cd /etc/apt
sudo cp sources.list sources.list.bak

# 2. 向/etc/apt/sources.list添加网易源
echo 'deb http://mirrors.163.com/debian/ jessie main non-free contrib' >> /etc/apt/sources.list && \
echo 'deb http://mirrors.163.com/debian/ jessie-updates main non-free contrib' >> /etc/apt/sources.list && \
echo 'deb http://mirrors.163.com/debian-security/ jessie/updates main non-free contrib' >> /etc/apt/sources.list

# 3. 更新源,这步骤不可少
apt-get update

接下来便可使用apt install vim来按装 vim 了。
说明:
(1)docker容器,默认root用户,是没有sudo命令的。
(2)这里推荐使用网易的源。阿里/中科大/清华的源有几率报错。比如在apt-get update的时候,阿里的源可能报错(Ubuntu的提示:the public key is not available)。可能是Docker提供的精简Ubuntu,在阿里的源下载验证无法通过。

5. Docker私有仓库

Docker pull的镜像默认来自官方的镜像仓库Docker Hub,一般我们会配置国内镜像仓库如阿里云、网易云等,这些仓库都是公用的,或者托管在第三方平台上的。但商业软件出于保密的需求,需要建立一个私有仓库。
用户可以使用Dokcer官方提供的镜像registry来搭建私有仓库。

1)准备好registry镜像(pull下来)

# 拉取registry镜像,不指定版本默认为最新的latest版本。
docker pull registry

在这里插入图片描述
输入 docker images 可以看到已经被pull下来了:
在这里插入图片描述

2)创建好一个新的本地仓库容器 local_registry

docker run -d -p 5000:5000 --name=local_registry --restart=always --privileged=true -v /home/hadoop/mydocker/images:/var/lib/registry registry:latest
  • -d: 容器以后台服务的形式运行
  • -p 5000:5000 : registry镜像默认监听了5000端口,因此利用run命令在创建、启动容器时候要使用-p指定端口映射。
  • --restart=always:容器在退出时总是重启。
  • --privileged=true:获取容器的特权,类似ubuntu系统的普通账户获取了root权限。
  • -v /home/hadoop/mydocker/images:/var/lib/registry registry:latest:将镜像上传到这个新建的local_registry容器的/var/lib/registry 目录下,通过 -v 在宿主机和容器之间建立映射,就可以将容器保存到宿主机的 -v /home/hadoop/mydocker/images 目录下。
  • registry:latest : 为前面刚拉取的 registry镜像,为最新版本 latest。(类似于ubuntu:20.04, centos:7)

3)上传镜像到仓库

发布镜像时,需要将image重新命名,即用tag标签起别名。否则会报错denied: requested access to the resource is denied
注意: 这里起别名不能乱起,开头要有标识,以便上传到仓库能被识别。

  • 命名格式一般为:dockerhub用户名/镜像名:版本
  • 如果是本地默认的5000端口,命名格式为: localhost:5000/镜像名:版本

这里我们的命名格式为: localhost:5000/镜像名:版本
例: 假设本地存在镜像ubuntu:20.04,要将其发布到上面新建的本地仓库local_registry中。如下:

# 打标签
docker tag ubuntu:20.04 localhost:5000/myubuntu:v1_20220101

# 查看镜像已有重命名的
docker images

# 发布镜像到本地仓库local_registry(localhost:5000)
docker push localhost:5000/myubuntu:v1_20220101

成功发布(push)到私有仓库的运行结果如下图:
在这里插入图片描述Pushed : 表成功发布。
sha256:9c152418e380c6e6dd7e19567bb6762b67e22b1d0612e4f5074bda6e6040c64a : 是镜像在仓库的sha256值,sha256是一种加密算法,类似于md5。

4)查看

(1)浏览器查看

上传完毕后,可以打开浏览器,访问 宿主机ip::5000/v2/_catalog 来查看刚上传的镜像。
若在本地,即访问: 127.0.0.1:5000/v2/_cataloglocalhost:5000/v2/_catalog
如下图,可看到上传的自己重命名的myubuntu镜像(前面已tag重命名为localhost:5000/myubuntu:v1_20220101
):
在这里插入图片描述

(2)目录查看

进入到local_registry容器,
注意使用 docker exec -it local_registry /bin/bash 进入失败,因为创建该容器的时候没有指定 /bin/bash。
我们要用sh命令来进入该容器:

docker exec -it local_registry sh

如下:
在这里插入图片描述在这里插入图片描述
可以看到push发布的镜像存在local_registry容器中的/var/lib/registry/docker/registry/v2/blobs/sha256 目录下。

6. Docker Compose 编排容器

6.1 安装

法1(推荐):通过apt安装(适用于Ubuntu)
sudo apt install docker-compose

通过

 which docker-compose

命令,可看到启动快捷位置在

/usr/bin/docker-compose
法2(推荐):通过pip安装
# 切换root用户
su
pip install docker-compose

验证:
输入

docker-compose -v

可以查看到版本,表示安装成功!如下图:
在这里插入图片描述
注意: 一定要切换成root用户安装,否则会因为权限问题导致docker-compose安装在home/用户名/.local/bin 下,导致直接输入docker-compose -v 找不到命令。
附: root用户安装的,切换成普通用户也能直接运行docker-compose,我的切换成名为hadoop的用户,如下:
在这里插入图片描述
那么我们可以直接启动的docker-compose安装在哪里了呢?我用的是anaconda的pip,自然是在anaconda目录下了,可以使用find命令全局搜索docker-compose验证一下,结果如下:
在这里插入图片描述

法3:通过github安装

从github下载docker-compose,安装位置为:/usr/local/bin/docker-compose

# 下载安装
curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 建立软链接
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

注释:

  • $(uname -s)$(uname -m) 是为了获取本机的信息,以便下载适合的版本。如下:
    在这里插入图片描述
    docker-compose-$(uname -s)-$(uname -m)docker-compose-x86_64_Linux
    此时输入
cd /usr/local/bin
./docker-compose -v

便可以看到版本信息。

  • 另外,与pip安装方式不同的是,这种安装方式要想在任意目录下使用docker-compose命令,则需要建立软链接,或者添加环境变量,/usr/bin/ 目录下的命令可以在任何目录下执行,不妨将其软链到 /usr/bin/ 目录下。

6.2 使用

任选一个位置新建一个目录 myflask(如/home/hadoop/mydocker/myflask),里面建4个文件:
app.py, docker-compose.yml, Dockerfile, requirements.txt。
在这里插入图片描述

(1)文件内容:

app.py:

import time
import redis
from flask import Flask


app = Flask(__name__)
cache = redis.Redis(host="redis", port=6379)


def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)


@app.route('/')
def hello():
    count = get_hit_count()
    return "Hello World! I have been seen {} times.\n".format(count)

docker-compose.yml:

version: '3'
services:
    web:
        build: .
        ports:
            - "5001:5000"
    redis:
        image: "redis:alpine"

Dockerfile:

FROM ubuntu:20.04
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apt-get update
RUN apt-get install python3.8 -y
RUN apt-get install python3-pip -y
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]

FROM centos:7
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0

# 替换阿里镜像加速
# RUN yum -y install epel-release
# RUN yum repolist

RUN yum update -y
RUN yum install python3 -y
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
CMD ["flask", "run"]

requirements.txt:

flask
redis
(2)构建服务
# 进入到刚新建的目录
cd /home/hadoop/mydocker/myflask

# 构建服务
docker-compose up
(3)验证查看

查看相关容器

docker-compose ps

主机浏览器输入 localhost:5001 可以访问到容器。
在这里插入图片描述

7. Portainer 可视化工具

使用命令管理容器是非常高效的,但不直观,对新手来说也不容易。所以,还有一个好用的可视化的容器运维工具Portainer。

7.1 安装

Portainer提供了一个官方的镜像,简化了部署过程。

(1)拉取镜像
# 默认下载最新的latest版本
docker pull portainer/portainer

在这里插入图片描述在这里插入图片描述

(2)创建容器(装portainer镜像)
docker run -d --privileged=true -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v /home/hadoop/mydocker/portainer_data:/portainer_data portainer/portainer:latest

注释:

  • -p 9000:9000 : 端口,等会主机可通过9000端口访问这个portainer的容器
  • -v /var/run/docker.sock:/var/run/docker.sock :左主机右容器。 冒号左边是左主机(目录)、 冒号右边是右容器(目录)
  • -v /home/hadoop/mydocker/portainer_data:/portainer_data : 同理
  • portainer/portainer:latest : 上面下载的最新latest版本的portianer镜像(可通过docker images查看)。
    输入
docker ps

查看正在运行的容器,可以看到新容器已创建成功并在运行,新容器名被默认自动设置为了 gracious_goldwasser ,如下:
在这里插入图片描述

(3)访问web

前面创建容器的时候设定了端口9000,可通过 主机ip:9000 来访问。
本地的话即:localhost:9000。如下:
首次登陆后让创建新用户,默认admin,密码自定义至少8位,可设置为12345678。进入后,界面如下:
在这里插入图片描述上图,可看到Portianer提供了4种不同的功能选择,由于本机使用的是单机操作Docker,所以选择Local面板,点击Connect 进入主界面。如下:
在这里插入图片描述上图,可以看到所有的容器信息:总共10个容器,4个在运行,6个关闭状态。
在这里插入图片描述接下来,点击上图箭头指向的空白区域可以进入Dashboard仪表盘,这里的信息更为丰富,如下:
在这里插入图片描述点击上图红框的"Containers"面板,可以进入容器列表界面,如下:
在这里插入图片描述在该界面可以管理容器:启动、停住、重启、暂停、删除、添加容器等功能。很直观~

8. 常见问题解决

8.1 启动不了docker

背景

怕占用资源,用systemctl disable docker将docker自启动关闭后,就启动不了docker了。

报错信息
Warning: The unit file, source configuration file or drop-ins of docker.service changed on disk. Run 'systemctl daemon-reload' to reloa>
● docker.service - LSB: Create lightweight, portable, self-sufficient containers.
     Loaded: loaded (/etc/init.d/docker; generated)
     Active: failed (Result: exit-code) since Wed 2022-12-31 19:35:41 CST; 20min ago
       Docs: man:systemd-sysv-generator(8)

12月 08 19:35:41 host systemd[1]: Starting LSB: Create lightweight, portable, self-sufficient containers....
12月 08 19:35:41 host docker[10404]:  * /usr/bin/dockerd not present or not executable
12月 08 19:35:41 host systemd[1]: docker.service: Control process exited, code=exited, status=1/FAILURE
12月 08 19:35:41 host systemd[1]: docker.service: Failed with result 'exit-code'.
12月 08 19:35:41 host systemd[1]: Failed to start LSB: Create lightweight, portable, self-sufficient containers..
分析

上面 loaded (/etc/init.d/docker; generated) 加载时,但 /usr/bin/dockerd not present or not executable 没有执行。

  • 看看 /etc/init.d/docker 里面确实用到了 dockerd
  • 但我的 /usr/bin/ 下只有了 docker,而没有了 dockerd,缺失!
    正常情况下终端直接输入 dockerdockerd 都会有提示,而此时:
    在这里插入图片描述
解决
apt install docker.io

会下载dockerd,然后重启dokcer便好用了。

9. docker实战

9.1 docker中安装mysql8.0,并用Navicat连接

1. docker中创建mysql容器

先拉取 mysql8.0 镜像

# 拉取mysql8.0镜像
docker pull mysql:8.0
# 查看镜像
docker images

创建容器,装入拉取好的mysql8.0镜像

# 创建容器并后台运行。主机通过3307端口对应着mysql容器的3306端口
docker run -td --name mysql_db --restart=always -p 3307:3306 -e MYSQL_ROOT_PASSWORD=root mysql:8.0

参数说明:

  • -i 交互模式
  • -t 分配伪终端
  • -d 后台运行
  • /bin/bash: 交互式 Shell
  • /bin/sh:

或者先创建容器,再启动容器,也一样。

docker create -it --name mysql_db --restart=always -p 3307:3306 -e MYSQL_ROOT_PASSWORD=root mysql:8.0
docker start mysql_db

在这里插入图片描述

2. 验证
1)容器内连接mysql

进入容器

docker exec -it mysql_db /bin/bash
# 等价: docker exec -it mysql_db bash

输入 mysql -uroot -p,密码 root,能成功连接mysql。

2)Navicat连接mysql

查容器IP。新装的极简版容器一般没有ifconfig命令,但由于容器和虚拟机一样走的是宿主机的网卡,所以可通过宿主机输入 ifconfig 来间接地查容器ip。
在宿主机输入ifconfig后,可以看到有一个 docker0 的网卡,我这里显示的ip为 172.17.0.1。在Navicat上用这个ip去连mysql(注意端口是3307,密码root)。
在这里插入图片描述(注意:如果这个ip连接不上,那么最下面那块网卡有个192.168.开头的ip,试试那个)
在这里插入图片描述

3. 保存迁移镜像

如果docker里的mysql存了很多数据了,且要用docker迁移到其他机器中。
i)当前电脑:

# 将容器提交成镜像
docker commit mysql_db mysql_db:v1
# 保存镜像
docker save -o mysql_db_v1.tgz mysql_db:v1

拿到 mysql_db_v1.tgz 文件,拷到另一台电脑。
ii)另一台电脑:

# 加载镜像
docker load -i mysql_db_v1.tgz
# 创建容器。只需要写明与主机对应的端口号即可!其他密码等都和原来镜像里一样。
docker create -it --name mysql_db -p 3307:3306 mysql_db:v1
# 启动容器
docker start mysql_db

同样,可以用navicat等连接测试。

9.2 docker拉取跨平台镜像(如docker_x64拉取arm版镜像)

命令
docker pull --platform=架构名 镜像名:版本号

例: 在x86的docker中拉取arm版的mysql:8镜像。

docker pull --platform=arm64 mysql:8
# 或 docker pull --platform=arm64 mysql:8.0

我的docker是20.10版本的,如果上面失败,那么按照下面修改配置文件试试,如下:

# 编辑 /etc/docker/daemon.json,使内容如下:
{
        "registry-mirrors":[
                "https://zlwmp571.mirror.aliyuncs.com",
                "https://docker.mirrors.ustc.edu.cn/",
                "https://reg-mirror.qiniu.com/",
                "https://hub-mirror.c.163.com/"
        ],
        "experimental":true
}



# 重新加载服务的配置文件
systemctl daemon-reload

# 重启docker
systemctl restart docker

# 拉取arm版的mysql:8镜像
docker pull --platform=arm64 mysql:8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值