LOADING

加载过慢请开启缓存 浏览器默认开启

基于阿里云ECS与ACR的容器镜像管理

基于阿里云ECS与ACR的容器镜像管理(基于Windows 11)


基本要求

  • 理解并掌握云服务器ECS、容器、镜像、镜像仓库等核心概念
  • 理解并掌握Docker基本原理与常用指令
  • 理解并掌握Dockerfile的撰写与容器镜像的构建
  • 了解并掌握创建与管理阿里云ECS服务器的基本操作
  • 了解并掌握基于阿里云容器镜像服务ACR创建与应用镜像仓库的基本操作

实验过程

环境搭建

准备云服务器ECS

访问云服务器ECS产品首页,选择相关配置后购买。其中操作系统选择Ubuntu,安全组配置默认应仅允许开启SSH(22),HTTP(80)与HTTPS(443)端口。

屏幕截图 2024-10-27 135030

屏幕截图 2024-10-27 143227

在ECS安装Docker引擎

访问Docker官网(docs.docker.com),根据提示在阿里云服务器ECS上安装Docker。

应该指出的是,国内现在已经无法正常访问Docker官网了。因此我们可以使用阿里云源安装Docker:

  • 检查是否已安装Docker
docker --version

屏幕截图 2024-10-27 143325

  • 更新系统包索引
sudo apt-get update

屏幕截图 2024-10-27 143500

  • 安装依赖
sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

屏幕截图 2024-10-27 143622

  • 添加 Docker GPG 密钥
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
  • 设置 Docker 仓库
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  • 更新包索引并安装 Docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

屏幕截图 2024-10-27 143931

  • 启动并验证 Docker

启动Docker服务并确保已经启动:

sudo systemctl start docker
sudo systemctl enable docker

验证Docker是否正确安装:

docker --version

屏幕截图 2024-10-27 144122

基于阿里云容器镜像服务ACR配置镜像仓库

访问阿里云容器镜像服务ACR产品首页(容器镜像服务_镜像构建_镜像授权_镜像托管-阿里云),点击“管理控制台”进入实例列表,创建一个个人实例:

  • 设置访问密码
  • 创建命名空间
  • 创建镜像仓库

使用名称npu,默认设置仓库为私有,代码源选择本地仓库。

屏幕截图 2024-10-27 145412

练习ECS基础操作

云服务器新手上路

完成阿里云云起实验室项目“ECS云服务器新手上路”(ECS云服务器新手上路 - 云起实验室),开展控制台管理实践。

创建配置普通用户
  • 在本地系统基于SSH访问ECS公网地址,使用root账号登录

首先需要开启Windows系统自带的SSH服务。

随后本地打开cmd,基于SSH远程访问ECS(root账号登录):

ssh <username>@<ECS公网ip> -p 22

屏幕截图 2024-10-27 150812

执行useradd命令,添加普通用户,使用passwd命令设置/重置用户密码:

sudo useradd -m -s /usr/bin/bash whim1		//-m 创建用户主目录;-s 设定Shell
passwd whim1		//设置登录密码
sudo usermod -aG sudo whim1		//编辑/etc/group,将指定用户加入sudo组,提供sudo权限
sudo usermod -G docker whim1		编辑/etc/group,将指定用户加入docker组,提供docker权限

屏幕截图 2024-10-27 151529

[!CAUTION]

sudo usermod -aG sudo whim1是正确的,而不是-G

使用新建用户进行SSH登录验证,且确认sudo su命令可以正常切换到root用户:

屏幕截图 2024-10-27 152311

屏幕截图 2024-10-27 152315

禁止root远程登录

编辑文件/etc/ssh/sshd_config,添加配置PermitRootLogin no

vim /etc/ssh/sshd_config

重启SSH服务

sudo service sshd restart
//或者执行sudo systemctl restart sshd

完成上述配置后,使用root用户进行SSH登录验证,确认配置生效:

屏幕截图 2024-10-27 153353

练习Docker常用命令

以高性能HTTP&反向代理Web服务器Nginx1.24.0为例,练习Docker常用命令。

拉取容器镜像
  • 使用命令docker search在Docker Hub查询镜像:
docker search nginx

屏幕截图 2024-10-27 155435

屏幕截图 2024-10-27 160425

由于国内无法拉取Docker镜像了,因而需要配置镜像源加速:

vim /etc/docker/daemon.json

添加以下内容

{
    "registry-mirrors": ["https://docker.1panel.live"]
}

保存后重启docker:

systemctl restart docker

[!CAUTION]

也可以使用AtomHub 可信镜像仓库平台 · OpenAtom Foundation,搜索需要的镜像名称,进行pull拉取,如:

docker pull atomhub.openatom.cn/amd64/redis:7.0.13
  • 使用docker pull从Docker Hub拉取容器镜像Nginx的最新版本:

屏幕截图 2024-10-27 160535

  • 拉取完成后,使用docker images命令查看本地镜像:

屏幕截图 2024-10-27 160741

基于镜像创建并运行容器
  • 简单创建运行

使用命令docker run进行简单创建与运行:

docker run -d --name nginx -p 80:80 nginx
# -d, --detach:在后台运行该docker容器,并在启动后打印容器ID
# --name:指定启动后的容器名称,本例设置容器实例名称为“nginx”
# -p,--publish list:端口发布(映射),<宿主端口>:<容器端口>
# 最后的“nginx”为镜像名,此处省略了冒号与紧跟其后的tag,默认tag为latest

使用命令docker ps可查看正在运行的容器信息:

docker ps

屏幕截图 2024-10-28 083311

此时使用浏览器访问ECS服务器公网IP,可见如下页面:

屏幕截图 2024-10-28 083421

  • 挂载宿主目录

实际应用时,对于容器中部署的服务,通常需把其所依赖的配置文件、数据文件进行持久化存储。否则一旦容器被销毁,这些文件也将随之销毁。

要满足此类需求,需要在容器创建运行时,将宿主系统中用于存储配置文件、代码文件、数据文件的目录甚至具体文件映射到容器中的对应目录或文件,即,让容器在创建启动时,从宿主系统中指定的目录文件加载配置文件,在生成数据时则写入宿主系统中指定的目录文件。

下面将为nginx服务的配置文件、日志文件以及Web服务的根目录分别建立持久化映射。nginx容器中的三个固有目录与宿主系统的目录映射关系定义为:

持久化内容 容器目录 宿主目录
总体配置 /etc/nginx/nginx.conf /opt/docker/nginx/nginx.conf
服务配置 /etc/nginx/conf.d /opt/data/nginx/conf.d
日志文件 /var/log/nginx /opt/log/nginx
Web服务 /usr/share/nginx/html /opt/share/nginx/html

首先在ECS上创建三个宿主目录:

mkdir -p /opt/docker/nginx/conf.d
mkdir -p /opt/docker/nginx/logs
mkdir -p /opt/docker/nginx/html
# -p, --parents:如果路径中任一级父目录不存在,则创建

屏幕截图 2024-10-31 154847

然后从先前启动的nginx容器中将配置文件复制到宿主(否则目录挂载后,若容器找不到配置文件,服务不能正常运行)

docker cp nginx:/etc/nginx/nginx.conf /opt/docker/nginx/
docker cp nginx:/etc/nginx/conf.d /opt/docker/nginx/
docker cp nginx:/usr/share/nginx/html /opt/docker/nginx/

屏幕截图 2024-10-31 154958

为重新运行挂载在宿主目录的nginx容器,必须停止并删除当前nginx容器。

首先停止运行当前nginx容器。

docker stop nginx
#除容器名称,也可使用容器id标识容器

屏幕截图 2024-10-31 155027

此时docker ps已查询不到已停止运行的nginx容器,但是应用参数-a,即可查看全部正在运行与停止运行的容器。停止的容器状态被标注为Exited,同时端口没有发布(映射)记录。

docker ps -a

屏幕截图 2024-10-31 155058

随后删除停止运行的nginx容器。删除后通过docker ps -a查看,确认已删除。

docker rm nginx
nginx
docker ps -a
#观察

屏幕截图 2024-10-31 155142

重新设置执行docker run,完成相关文件与目录的挂载。

# -v, --volume list:挂载(绑定)目录,<宿主目录>:<容器目录>
docker run -d --restart=always \
        --name nginx \
        -p 80:80 \
        -v /opt/docker/nginx/nginx.conf:/etc/nginx/nginx.conf \
        -v /opt/docker/nginx/conf.d:/etc/nginx/conf.d \
        -v /opt/docker/nginx/html:/usr/share/nginx/html \
        -v /opt/docker/nginx/logs:/var/log/nginx \
        nginx

屏幕截图 2024-10-31 155340

停止,启动,进出容器

关闭刚创建的挂载了宿主目录的nginx容器,随后使用docker start命令启动该容器。

docker stop nginx
nginx
docker start nginx
nginx

屏幕截图 2024-10-31 155415

启动后,换命令行方式快速在ECS进行Nginx服务验证。

curl 127.0.0.1:80
#使用curl访问ECS本地服务端口,输出Nginx默认HTML页面

屏幕截图 2024-10-31 155443

重启容器nginx后,使用docker exec命令进入容器。该命令本身定义为在容器内部运行一条指定命令,通过指定命令为Shell程序,如/bin/bash,配合应用参数-it,可实现进入容器进行命令行交互式操作。

docker exec -it nginx /bin/bash
# -i --interactive,保持交互模式
# -t --tty,分配一个伪终端(模拟终端)
# nginx,容器名称
# /bin/bash,待执行的命令。进入bash shell

进入容器后,可执行容器本身所支持的命令操作。此时尝试进入/usr/share/nginx/html目录,创建一个test.html文件。

因为该容器不支持编辑命令vim,所以使用echo命令创建Web文件test.html,浏览器访问该文件时,将展示h1大小的Hello,world

完成容器内的文件创建后,使用exit命令退出容器,查看宿主目录ls /opt/docker/nginx/html,可见在容器内创建的test.html文件,已成功持久化存储到宿主系统。此时使用curl访问ECS本地URL127.0.0.1:80/test.html,可成功输出test.html文件内容。

下面以(nginx)$作为容器内命令行提示符:

(nginx)$ cd /usr/share/nginx/html
(nginx)$ echo "<h1>Hello,world</h1>" > test.html
(nginx)$ exit
ls /opt/docker/nginx/html
50x.html  index.html  test.html
curl 127.0.0.1:80/test.html

屏幕截图 2024-10-31 173220

完成以上步骤后,用浏览器访问http://<ECS公网地址>/test.html,观察h1大小的Hello,world

屏幕截图 2024-10-31 173517

查看容器日志

使用docker logs命令查看容器的日志输出。

docker logs nginx

屏幕截图 2024-10-31 174241

删除容器镜像
docker rmi nginx
# rmi: remove images;也可使用docker image rm nginx

屏幕截图 2024-11-01 110626

因为尚有基于该镜像创建的容器存在,所以无法删除该镜像,需首先停止、删除容器实例后再行删除容器镜像。

docker stop nginx
nginx
docker rm nginx
nginx
docker rmi nginx

docker images
# 自行观察

屏幕截图 2024-11-01 110917

构建Docker容器镜像

以Ubuntu镜像作为基础镜像,拟制作一个包含Python基础环境以及Nginx服务器的新镜像。整个制作过程包含两大步骤,一是撰写Dockerfile文件,二是使用docker build命令基于Dockerfile创建新镜像。

编写Dockerfile文件

Dockerfile是制作Docker容器镜像的基础。一般而言,Dockerfile文件指令逻辑应按照以下模式建立:选择合适的基础镜像、安装基础工具与依赖、添加其他应用、清理缓存、声明镜像端口暴露情况、设置默认启动命令。

  • 编写命令
vim 文件名

屏幕截图 2024-11-01 114802

  • 选择基础镜像Ubuntu并添加文件维护者信息
# 使用Ubuntu作为基础镜像
FROM ubuntu:22.04
# 维护者信息
LABEL maintainer="<维护者邮箱>"
  • 设置工作目录
WORKDIR /app
  • 安装Nginx&Python
# 安装nginx&Python
RUN apt-get update && apt-get install -y \
    nginx \
    python3 \
    python3-distutils
  • 清理apt软件包缓存
RUN rm -rf /var/lib/apt/lists/*
  • 声明暴露端口
EXPOSE 80
  • 设置启动命令
CMD ["nginx","-g","daemon off;"]
  • Dockerfile完整逻辑:
FROM ubuntu:22.04
LABEL maintainer="<维护者邮箱>"

WORKDIR /app

RUN apt-get update && apt-get install -y \
    nginx \
    python3 \
    python3-distutils
    
RUN rm -rf /var/lib/apt/lists/*
EXPOSE 80
CMD ["nginx","-g","daemon off;"]

输入完之后,敲下esc,然后:wq保存并退出。

屏幕截图 2024-11-01 114740

基于Dockerfile创建容器镜像

基于Dockerfile,使用docker build命令创建容器镜像。创建完成后,通过docker images观察新建镜像的大小。

docker build -f dockerfile-npu -t npu .

docker images

屏幕截图 2024-11-01 115345

屏幕截图 2024-11-01 115419

运行该镜像,访问80端口,检测Nginx服务。随后进入容器,检测Python解析能力。

docker run -d --name npu -p 80:80 npu

curl 127.0.0.1
# 等价于127.0.0.1:80,或者http://127.0.0.1:80
docker exec -it npu /bin/bash
(nginx)$ python3
(nginx)$ exit()
(nginx)$ exit

屏幕截图 2024-11-04 104310

屏幕截图 2024-11-04 104319

屏幕截图 2024-11-04 104334

ACR镜像管理与应用

实际应用时,开发者通常需要配置持续集成与持续部署流水线,在“构建镜像”阶段,将代码打包到基础镜像后,推送至特定镜像仓库,而在“服务部署”阶段则从镜像仓库拉取该镜像并部署于特定ECS服务器或集群。

下面练习基于阿里云容器镜像服务与命令行Docker指令的镜像推送与拉取。

推送容器镜像至ACR

重新标记刚创建的镜像npu,以满足推送该镜像至ACR的要求。镜像名包括“镜像仓库”与“标记”两部分。此时要推送的仓库是阿里云容器镜像服务ACR中所创仓库。

访问之前在阿里云ACR控制台创建的镜像仓库npu,查询镜像仓库URL,并使用仓库地址重新标记镜像npu

docker tag npu crpi-exr3j7gox2plovb8.cn-heyuan.personal.cr.aliyuncs.com/whim111/npu

![屏幕截图 2024-11-04 113523](https://cdn.jsdelivr.net/gh/Whimsically1/ImgServer/基于阿里云ECS与ACR的容器镜像管理/屏幕截图 2024-11-04 113523.png)

登录阿里云ACR,使用命令docker push推送镜像至ACR镜像仓库npu

docker login --username=沙里院的雪 crpi-exr3j7gox2plovb8.cn-heyuan.personal.cr.aliyuncs.com

docker push crpi-exr3j7gox2plovb8.cn-heyuan.personal.cr.aliyuncs.com/whim111/npu

屏幕截图 2024-11-04 114848

镜像上传成功。此时查看阿里云ACR控制台,在镜像仓库npu的“镜像版本”页面,可见刚提交的镜像记录。

拉取容器镜像至ECS

为测试从阿里云ACR拉取到ECS的容器镜像是否能正常工作,首先需要删除ECS本地相关的容器以及镜像,以免干扰测试。

docker stop npu

docker rm npu

docker rmi npu

docker rmi crpi-exr3j7gox2plovb8.cn-heyuan.personal.cr.aliyuncs.com/whim111/npu

docker images

屏幕截图 2024-11-04 115032

此时在ECS上执行拉取镜像操作,随后创建运行容器并测试服务效果。

docker pull crpi-exr3j7gox2plovb8.cn-heyuan.personal.cr.aliyuncs.com/whim111/npu

docker run -d --name npu -p 80:80 crpi-exr3j7gox2plovb8.cn-heyuan.personal.cr.aliyuncs.com/whim111/npu

curl 127.0.0.1
# 自行观察,确认从阿里云ACR拉取的镜像无误,可创建容器通过服务测试。

屏幕截图 2024-11-04 134417

屏幕截图 2024-11-04 134426