制作Docker镜像
一、Docker构建镜像的原理
1、镜像分层原理
Docker镜像是由一系列只读的层(layers)组成的,每个层代表了一组文件系统的更改。这些更改可以是添加文件、删除文件、修改文件等操作。镜像的最底层通常是一个基础镜像,比如基于CentOS、Ubuntu、Alpine等操作系统。往上每一层代表了Dockerfile中每个指令的执行结果。重要的是,每一层都是不可变的,一旦创建就不会被修改,新的更改会在其上新建一层。
2、Docker的镜像结构
docker的分层镜像结构如图所示,镜像的最底层必须是一个启动文件系统(bootfs
)的镜像层。bootfs
的上层镜像称为根镜像(rootfs
)或者基础镜像(Base Image
),它一般是操作系统,比如centos、debian或者Ubuntu。
用户的镜像必须构建在基础镜像之上。如图所示,emacs镜像层就是在基础镜像上安装emacs创建出来的镜像,在此基础上安装apache又创建了新的镜像层。利用这个新的镜像层启动的容器里运行的是一个已经安装好emacs和apache的Debian系统。
3、分层存储原理
Docker镜像采用UnionFS(联合文件系统,如AUFS、OverlayFS等)实现分层存储。UnionFS允许将多个文件系统层次叠加以形成一个单一的合并视图。对于Docker镜像来说,每个层都是只读的,除了最顶层的可写层(在容器运行时创建)。
- 基础层:通常是操作系统层,包含最低级别的文件和库。
- 中间层:由Dockerfile中的每个指令生成,每个层都是对前一层的增量修改。
- 读写层(容器层):容器运行时,会在镜像的顶部添加一个可写的层,用于保存容器运行时的所有改动。
4、构建命令与层的关系
- 在Dockerfile中,每个
RUN
、COPY
、ADD
等指令执行后,都会在现有镜像基础上添加一个新的只读层。 - 如果指令没有导致文件系统的变化(例如,执行一个检查系统状态的命令但不改变任何文件),Docker可能不会创建新的层。
- 重复的构建步骤可以通过Docker的缓存机制避免重复执行,从而加速构建过程。
5、最终镜像的创建
构建过程的最后,Docker将所有这些层组合起来,并为这个组合赋予一个唯一的ID,这就是最终的Docker镜像。这个镜像可以被打上标签(tag),便于识别和后续的拉取、推送操作。
二、docker commit 构建镜像
1、使用场景
- 构建临时的测试镜像;
- 容器被入侵后,使用docker commit,基于被入侵的容器构建镜像,从而保留现场,方便以后追溯。
2、手动制作yum版的nginx镜像
2.1、启动一个centos容器,安装好常用的软件以及nginx
[root@localhost ~]# docker run -it --name centos-v1 centos:7 bash
[root@95ef0464ffb2 /]# yum install -y epel-release
[root@95ef0464ffb2 /]# yum install -y nginx
[root@95ef0464ffb2 /]# yum install -y wget vim pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop
2.2、关闭nginx后台运行
[root@95ef0464ffb2 /]# sed -i '/^pid \/run\/nginx.pid;$/a daemon off;' /etc/nginx/nginx.conf
[root@95ef0464ffb2 /]# egrep -v "^$|^#" /etc/nginx/nginx.conf | head -5
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
daemon off;
2.3、自定义web页面
[root@95ef0464ffb2 /]# echo 'hello yum_nginx' > /usr/share/nginx/html/index.html
2.4、提交为镜像
docker commit -m "my first nginx image v1" centos-v1 centos_nginx:v1
2.5、从自己的镜像启动容器
docker run -d -p 8080:80 --name my_centos_nginx centos_nginx:v1 /usr/sbin/nginx
三、DockerFile
1、什么是DockerFile
DockerFile 是一个用于自动构建 Docker 镜像的文本文件,其中包含了用户可以给出的所有构建镜像所需的指令和参数。
这个文件按照从上至下的顺序定义了一系列构建镜像的步骤,每个指令通常对应于镜像中的一个层。
DockerFile 的设计使得镜像的创建过程高度可编程、可重复及可共享,有利于实现持续集成和持续部署(CI/CD)的工作流程。
2、DockerFile构建镜像过程
1、首先,创建一个目录用于存放应用程序以及构建过程中使用到的各个文件等;
2、然后,在这个目录下创建一个Dockerfile文件,一般建议Dockerfile的文件名就是Dockerfile;
3、编写Dockerfile文件,编写指令,如,使用FROM 指令指定基础镜像,COPY指令复制文件,RUN指令指定要运行的命令,ENV设置环境变量,EXPOSE指定容器要暴露的端口,WORKDIR设置当前工作目录,CMD容器启动时运行命令,等等指令构建镜像;
4、Dockerfile编写完成就可以构建镜像了,使用docker build -t 镜像名:tag
. 命令来构建镜像,最后一个点是表示当前目录,docker会默认寻找当前目录下的Dockerfile文件来构建镜像,如果不使用默认,可以使用-f参数来指定dockerfile文件,如:docker build -t 镜像名:tag -f /xx/xxx/Dockerfile
;
5、使用docker build命令构建之后,docker就会将当前目录下所有的文件发送给docker daemon,顺序执行Dockerfile文件里的指令,在这过程中会生成临时容器,在临时容器里面安装RUN指定的命令,安装成功后,docker底层会使用类似于docker commit命令来将容器保存为镜像,然后删除临时容器,以此类推,一层层的构建镜像,运行临时容器安装软件,直到最后的镜像构建成功。
四、DockerFile的常用指令
1、FROM
指定基础镜像,必须为第一个命令
1.1、指令格式
FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
- FROM指令用于指定基础镜像
- –platform选项可用在FROM多平台镜像的情况下指定平台。例如,linux/amd64、lunux/arm64、windows/amd64。
- AS name表示为构建阶段命令,在后续FROM和COPY --from=name说明中可以使用这个名词,引用此阶段构建的映像。
- tag或digest值是可选的。如果您省略其中任何一个,构建器默认使用latest标签。如果找不到指定tag,构建起将返回错误。
- 为了保证镜像精简,可以选用体积较小的Alpin或Debian作为基础镜像
1.2、示例
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
FROM extras:${CODE_VERSION}
CMD /code/run-extras
2、ARG
定义创建镜像过程中使用的变量
ARG是唯一可以位于FROM指令之前的指令
2.1、指令格式
ARG <name>[=<default value>]
<name>
是变量名,[=<default value>]
是可选的默认值。
2.2、作用域
ARG变量的定义从其在Dockerfile中的定义行开始生效,并在构建阶段结束时失效。
要在多个构建阶段使用相同的ARG,每个阶段都需要重新声明ARG。
2.3、预定义ARG
Docker预定义了一系列ARG变量,如HTTP_PROXY、HTTPS_PROXY等,这些可以在构建时不需在Dockerfile中声明,直接通过命令行的--build-arg
使用。
2.4、示例
FROM busybox
ARG user1
ARG buildno=1
在这个例子中,
user1
没有默认值,而buildno
的默认值是1。
3、LABEL
为生成的镜像添加元数据标签信息
这些元数据以键值对的形式存在
3.1、指令格式
LABEL <key>=<value> <key>=<value> <key>=<value> ...
- 键(key):应当是唯一的标识符,用于描述标签的内容类别。
- 值(value):与键相关联的具体数据内容,可以包含任何字符串,包括空格。如果值中需要包含空格或特殊字符,应使用双引号包围并适当使用转义字符(如
\
)。
3.2、示例
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
3.3、多个标签
可以在单行或多行上指定多个标签,尽管这样做在Docker 1.10版本后不再减少最终镜像的大小,但仍然是一种组织代码的可选方式
3.4、单行多标签
LABEL multi.label1="value1" multi.label2="value2" other="value3"
3.5、多行多标签(推荐)
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
使用双引号而非单引号:当值中包含环境变量插值等需要解析的元素时,必须使用双引号,因为单引号会阻止变量展开。
如果基础镜像(即FROM指令指定的镜像)中已经包含了某些标签,那么这些标签会被继承。如果有相同键的标签在新镜像的Dockerfile中被重新定义,那么新定义的值将覆盖原有的值。
3.6、查看镜像标签
docker image inspect --format='{{json .Config.Labels}}' myimage
{
"com.example.vendor": "ACME Incorporated",
"com.example.label-with-value": "foo",
"version": "1.0",
"description": "This text illustrates that label-values can span multiple lines.",
"multi.label1": "value1",
"multi.label2": "value2",
"other": "value3"
}
4、EXPOSE
声明镜像内服务监听的端口
- 文档作用:
EXPOSE
主要是为了提供一种文档记录的方式,帮助理解容器设计意图中哪些端口需要被外部访问。它不改变容器的实际行为,也不直接导致端口暴露给宿主机或其他网络服务。 - TCP与UDP:默认情况下,如果没有指定协议,
EXPOSE
认为端口使用TCP协议。你也可以明确指定端口为UDP,如EXPOSE 80/udp
。若需同时支持TCP和UDP,需分别声明两次:EXPOSE 80/tcp
和EXPOSE 80/udp
。 - 运行时覆盖:尽管Dockerfile中指定了
EXPOSE
,但在运行容器时,可以通过docker run
的-p
标志灵活地重写这些设置,比如映射到不同的宿主机端口,或者更改协议。
4.1、指令格式
EXPOSE <port> [<port>/<protocol>...]
4.2、示例:同时监听TCP和UDP协议的端口
EXPOSE 80/tcp
EXPOSE 80/udp
docker run -p 80:80/tcp -p 80:80/udp ...
5、ENV
用于设置环境变量
5.1、指令格式
ENV <key>=<value> ...
- 设置环境变量:允许为后续构建阶段中的所有指令设置环境变量,变量名是
<key>
,变量值是<value>
。这些环境变量可以在后续的RUN
、CMD
等指令中通过引用,支持环境变量替换。 - 嵌套解析:环境变量的值可以包含或引用其他环境变量,并且支持使用引号和反斜杠来包含空格或特殊字符,但引号会被移除,除非转义。
5.2、示例
ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy
ENV MY_NAME="John Doe" MY_DOG=Rex\ The\ Dog \
MY_CAT=fluffy
#批量设置
5.3、持续性
- 持久化:通过
ENV
设置的环境变量不仅在构建阶段有效,还会保留在从该镜像创建的容器中。你可以使用docker inspect
查看这些值,通过docker run --env <key>=<value>
来覆盖它们。 - 继承性:在多阶段构建中,子阶段会继承父阶段设置的环境变量。
5.4、注意事项
-
副作用:环境变量的持久性可能导致意料之外的行为变化。例如,设置
DEBIAN_FRONTEND=noninteractive
会改变apt-get
的行为,可能给镜像的使用者带来混淆。 -
构建时使用:如果环境变量只在构建过程中需要,而在最终镜像中不需要,可以考虑在单独的命令中设置,如:
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y ...
-
使用ARG:或者,可以使用
ARG
指令来设置构建时的变量,这些变量不会保存在最终的镜像中。
6、ADD
用于将文件、目录或远程文件URL添加到镜像的文件系统中
6.1、指令格式
ADD [OPTIONS] <src> ... <dest>
ADD [OPTIONS] ["<src>", "<dest>"]
<src>
可以是本地路径、通配文件、目录或URL。支持通配符(如*
?、
)。URL要求绝对路径必须指向文件。<dest>
目标路径,绝对或相对于当前WORKDIR
。指定目录。如果<dest>
结尾是/
且<src>
是URL,Docker会根据URL中的文件名来命名解压,解压后的文件保存在指定的目录中。
6.2、选项
--keep-git-dir
: 保留远程Git仓库中的.git
目录。
--checksum
: 验证资源的校验签。
--chown
: 设置文件权限。
--link
:硬链接处理。
--exclude
:排除模式匹配的文件或目录。
6.3、示例
1、通配符匹配
ADD hom* /mydir/
#添加以"hom"开头的所有文件到mydir目录中
ADD hom?.txt /mydir/
#单字符匹配
2、相对路径
<dest>
是相对路径,它会相对于当前的WORKDIR
ADD test.txt relativeDir/
#将test.txt添加到relativeDir内
3、绝对路径
若<dest>
以斜杠开头,它是绝对路径。
ADD test.txt /absoluteDir/
#将test.txt添加到absoluteDir根目录下
4、特殊字符处理
如果文件名包含如方括号等特殊字符,需要按照Go语言规则转义路径
ADD arr[[]0].txt /mydir/
7、COPY
编写Dockerfile的时候copy宿主机文件到镜像中。
7.1、指令格式
COPY [OPTIONS] <src> ... <dest>
COPY [OPTIONS] ["<src>", ... "<dest>"]
7.2、选项
--from=<name>
:从之前的构建阶段或指定的镜像中拷贝文件,而非当前构建上下文。--chown=<user>:<group>
:设置拷贝文件的用户和组所有权。--chmod=<perms>
:设置拷贝文件的权限模式。--link[=<boolean>]
:启用链接层机制,使得文件独立于前序层,优化缓存使用。--parents[=<boolean>]
:保留源路径中的父目录结构。--exclude=<pattern>
:排除符合指定模式的文件或目录
7.3、COPY --from
允许从一个已有的镜像、构建阶段或者其他命名的上下文中复制文件
FROM alpine AS build
COPY . .
RUN apk add clang
RUN clang -o /hello hello.c
FROM scratch
COPY --from=build /hello /
在一个多阶段构建中,可以指定从名为
build
的构建阶段复制文件
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
#也可以直接从其他镜像复制文件,比如从官方的Nginx镜像中复制配置文件
7.4、COPY --chown 和 COPY --chmod
COPY [--chown=<用户>:<组>] [--chmod=<权限>...] <源路径>... <目标路径>
COPY --chown=55:mygroup files* /somedir/
COPY --chown=bin files* /somedir/
COPY --chown=1 files* /somedir/
COPY --chown=10:11 files* /somedir/
COPY --chown=myuser:mygroup --chmod=644 files* /somedir/
7.5、COPY --link
COPY [--link[=<布尔值>]] <源路径> ... <目标路径>
# syntax=docker/dockerfile:1
FROM alpine
COPY --link /foo /bar
相当于
FROM alpine
# 第一个构建
FROM scratch
COPY /foo /bar
# 第二个构建,并将两个镜像的所有层合并在一起
8、USER
用于设置后续当前构建阶段中默认使用的用户名(或 UID)以及可选的用户组(或 GID)。
如果所指定的用户没有主组,那么镜像(或之后的指令)将会以根组(root group)的身份运行。
8.1、指令格式
USER <user>[:<group>]
USER <UID>[:<GID>]
8.2、示例
FROM microsoft/windowsservercore
# 在容器中创建 Windows 用户
RUN net user /add patrick
# 为后续指令设置用户 patrick
USER patrick
9、WORKDIR
用于为 Dockerfile 中随后的
RUN
,CMD
,ENTRYPOINT
,COPY
, 和ADD
指令设置工作目录。如果指定的工作目录不存在,即使之后的 Dockerfile 指令未使用到它,也会被创建。
9.1、指令格式
WORKDIR /path/to/workdir
9.2、示例
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
Dockerfile 中可以多次使用
WORKDIR
指令。如果给出的是相对路径,它将是相对于前一个WORKDIR
指令的路径。最后的
pwd
命令的输出将是/a/b/c
。
10、VOLUME
创建一个数据卷挂载点
10.1、指令格式
VOLUME ["/data"]
10.2、示例
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol
这个 Dockerfile 将生成一个镜像,使得执行 docker run 时会在 /myvol 创建一个新的挂载点,并将 greeting 文件复制到新创建的卷里。
10.3、注意事项
- 在基于 Windows 的容器上,容器内卷的目标必须是:
- 一个不存在或为空的目录
- 除了 C: 以外的其他驱动器
- 若在 Dockerfile 中声明卷后,有任何构建步骤修改了卷内的数据,这些更改将会被丢弃。
- 列表解析遵循 JSON 数组格式。你需要使用双引号(")而不是单引号(')来包围文本。
- 宿主机目录是在容器运行时声明的:由于宿主机目录(即挂载点)依附于特定宿主机,为了保持镜像的可移植性(因为无法确保特定的宿主机目录在所有宿主机上都存在),你不能在 Dockerfile 中直接从宿主机挂载目录。VOLUME 指令不支持指定宿主机目录参数。你需要在创建或启动容器时指定挂载点。
11、ENTRYPOINT
指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数
每个DockerFile中只能有一个ENTRYPOINT,当指定多个时只有最后一个起效
11.1、指令格式
ENTRYPOINT ["executable", "param1", "param2"]
#exec形式
ENTRYPOINT command param1 param2
#shell形式
11.2、示例
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
当你运行这个容器时,可以看到
top
是唯一的进程:
docker run -it --rm --name test top -H
12、RUN
运行指定命令
每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像层
当命令较长时可以使用\来换行
12.1、指令格式
RUN [OPTIONS] <command> ...
#shell形式
RUN [OPTIONS] [ "<command>", ... ]
#exec形式
12.2、示例:缓存Go包
# syntax=docker/dockerfile:1
FROM golang
RUN --mount=type=cache,target=/root/.cache/go-build \
go build ...
12.3、示例:缓存apt包
# syntax=docker/dockerfile:1
FROM ubuntu
RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt update && apt-get --no-install-recommends install -y gcc
12.4、示例:访问GitLab
# syntax=docker/dockerfile:1
FROM alpine
RUN apk add --no-cache openssh-client
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan gitlab.com >> ~/.ssh/known_hosts
RUN --mount=type=ssh \
ssh -q -T [email protected] 2>&1 | tee /hello
# "Welcome to GitLab, @GITLAB_USERNAME_ASSOCIATED_WITH_SSHKEY" should be printed here
# with the type of build progress is defined as `plain`.
eval $(ssh-agent)
ssh-add ~/.ssh/id_rsa
(Input your passphrase here)
docker buildx build --ssh default=$SSH_AUTH_SOCK .
13、CMD
CMD指令用来指定启动容器时默认执行的命令
13.1、指令格式
CMD ["executable","param1","param2"]
#相当于执行executable param1 param2
CMD ["param1","param2"]
#提供给ENTRYPOINT的默认参数
CMD command param1 param2
#在默认的shell中执行,提供给需要交互的应用
每个Dockerfile 只能有一条CMD
命令。如果指定了多条命令,只有最后一条会被执行
13.2、注意事项
如果使用
CMD
为ENTRYPOINT
指令提供默认参数,那么CMD
和ENTRYPOINT
指令都应该以exec形式指定。
RUN
实际上运行一个命令并提交结果;CMD
在构建时不执行任何操作,但指定了镜像的预期命令。
五、DockerFile制作镜像(制作nginx镜像)
1、下载centos镜像
docker pull centos:7
2、创建对应目录
mkdir -pv dockerfile/{web/{nginx,apache},system/{centos,ubuntu}}
3、进入指定目录下载源码包
[root@localhost ~]# cd dockerfile/web/nginx/
[root@localhost nginx]# pwd
/root/dockerfile/web/nginx
[root@localhost nginx]# wget http://nginx.org/download/nginx-1.20.1.tar.gz
[root@localhost nginx]# ls
nginx-1.20.1.tar.gz
4、编写DockerFile
[root@localhost nginx]# vim Dockerfile
FROM centos:7
MAINTAINER misakivv [email protected]
RUN yum install -y vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop
ADD nginx-1.20.1.tar.gz /usr/local/src/
RUN cd /usr/local/src/nginx-1.20.1 \
&& ./configure --prefix=/usr/local/nginx --with-http_sub_module \
&& make \
&& make install \
&& cd /usr/local/nginx
# ADD nginx.conf /usr/local/nginx/conf/nginx.conf
RUN useradd -s /sbin/nologin nginx \
&& ln -sv /usr/local/nginx/sbin/nginx /usr/sbin/nginx \
&& echo 'test nginx !' > /usr/local/nginx/html/index.html
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
4.1、解析
FROM centos:7
: 基于CentOS 7镜像来创建新的Docker镜像。这是构建过程的起点。MAINTAINER misakivv [email protected]
: 指定维护者的信息,包括姓名(或昵称)和联系方式。不过,这个指令在Dockerfile最佳实践中已不再推荐使用,建议使用LABEL替代以提供更多元数据信息。RUN yum install -y vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop
: 安装一系列必要的软件包,包括开发工具、编译器、Nginx依赖库等,-y
参数表示自动确认安装过程中的所有提示。ADD nginx-1.20.1.tar.gz /usr/local/src/
: 将当前目录下的nginx-1.20.1.tar.gz
文件添加到容器的/usr/local/src/
目录中。- 接下来的几行命令是在容器内编译并安装Nginx:
cd /usr/local/src/nginx-1.20.1
: 进入刚刚解压的Nginx源代码目录。./configure --prefix=/usr/local/nginx --with-http_sub_module
: 配置Nginx,指定安装路径为/usr/local/nginx
,并启用http_sub_module模块,该模块用于字符串替换,增强URL重写能力。make && make install
: 编译并安装Nginx。cd /usr/local/nginx
: 回到Nginx的安装目录。
- 注释掉的
# ADD nginx.conf /usr/local/nginx/conf/nginx.conf
行原本打算将自定义的nginx配置文件复制到Nginx配置目录,但已被注释,意味着使用Nginx默认配置。 RUN useradd -s /sbin/nologin nginx
: 创建一个名为nginx的系统用户,并且该用户不能登录(-s /sbin/nologin)。&& ln -sv /usr/local/nginx/sbin/nginx /usr/sbin/nginx
: 创建一个软链接,使得可以从系统的标准路径调用Nginx可执行文件。&& echo 'test nginx !' > /usr/local/nginx/html/index.html
: 在Nginx的默认网页目录创建一个简单的测试索引页。EXPOSE 80 443
: 声明容器运行时需要监听的端口,分别是HTTP(80)和HTTPS(443)端口。CMD ["nginx", "-g", "daemon off;"]
: 设置容器启动时执行的命令,这里是以非守护进程模式启动Nginx,方便直接查看输出和进行调试。
5、构建镜像
[root@localhost nginx]# docker build -t nginx:v1 .
[root@localhost nginx]# docker images | grep v1
nginx v1 e5d32f022cdc 56 seconds ago 650MB
6、测试验证
[root@localhost nginx]# docker run -itd -p 8088:80 nginx:v1
0c2810cb9b168890b59264a1990dcc5b5e8782e337a757c99d42dc061cb08a7c
六、镜像上传
1、阿里云仓库
1.1、注册账户
1.2、创建个人版实例
1.3、设置Registry登录密码
1.4、创建镜像仓库
1.5、登录阿里云Docker Registry
docker login --username=misaki0 registry.cn-hangzhou.aliyuncs.com
用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。
您可以在访问凭证页面修改凭证密码。
1.6、将镜像推送到Registry
docker tag nginx:v1 registry.cn-hangzhou.aliyuncs.com/misaki_nginx/my_nginx:v1
#将本地nginx:v1镜像创建标签并归属到阿里云镜像服务的指定仓库中
docker push registry.cn-hangzhou.aliyuncs.com/misaki_nginx/my_nginx:v1
#将重新标记的镜像推送到阿里云的容器镜像仓库中
2、Docker Hub上传镜像
目前我还没注册,暂时写不了这部分的镜像上传
但基本思路还是注册登录账户--> 本地登录仓库--> 给需要上传的镜像tag标签 --> docker push -->官网验证即可
热门相关:攻略初汉 来自地狱的男人 我的全世界就是你 间谍的战争 豪门宠婚:权少夫人萌上天