在Incus容器中运行Docker的完整指南

本文详细介绍了如何在Incus系统容器中运行Docker的两种方法,包括传统方法和新方法。涵盖了存储驱动配置、安全设置、Docker安装步骤以及测试容器部署,适合需要在隔离环境中运行Docker的开发者。

如何在Incus容器中运行Docker

Incus和Docker都使用Linux内核功能来容器化应用程序。当您需要像传统VM一样的系统级容器并提供持久化开发体验时,Incus是最佳选择。另一方面,Docker容器是临时的,当Docker容器停止或删除时,其中创建的所有文件都会丢失,除非您使用卷将它们存储在Docker之外的不同目录中。Docker被创建为一次性应用部署系统。Incus容器通常不是一次性创建的,停止时数据会保留在内部。由于Linux内核支持嵌套功能,您可以在Incus中运行Docker。

教程详情

  • 难度级别:简单
  • Root权限:不需要
  • 要求:Linux终端
  • 类别:Incus
  • 先决条件:Incus服务器
  • 操作系统兼容性:AlmaLinux、Alpine、Amazon Linux、Arch、CentOS、Debian、Fedora、Linux、Mint、openSUSE、Pop!_OS、RHEL、Rocky、Slackware、Stream、SUSE、Ubuntu
  • 预计阅读时间:6分钟

使用传统(旧)方法在Incus中设置Docker

在此方法中,您将学习:

  • 如何使用Docker和btrfs创建Incus容器
  • 如何在Incus容器中安装Docker
  • 部署测试容器

步骤1-使用Docker和btrfs文件系统创建Incus容器

我只使用BTRFS文件系统进行了测试。ZFS不支持Docker,除非您对Linux上的ZFS有丰富经验,否则不建议在生产环境中使用zfs Docker存储驱动程序。因此,最好使用BTRFS作为后端驱动程序。使用以下命令列出存储驱动程序:

1
$ incus storage list

输出

1
2
3
4
5
+---------+--------+-------------------------------------+---------+---------+
|  NAME   | DRIVER |             DESCRIPTION             | USED BY |  STATE  |
+---------+--------+-------------------------------------+---------+---------+
| default | btrfs  | nixCraft VM & Containers Production | 1       | CREATED |
+---------+--------+-------------------------------------+---------+---------+

如果存储驱动程序不是btrfs,请按以下方式创建:

1
2
$ incus storage create docker btrfs
$ incus storage list

输出

1
2
3
4
5
6
7
+---------+--------+-------------------------------------+---------+---------+
|  NAME   | DRIVER |             DESCRIPTION             | USED BY |  STATE  |
+---------+--------+-------------------------------------+---------+---------+
| default | btrfs  | nixCraft VM & Containers Production | 7       | CREATED |
+---------+--------+-------------------------------------+---------+---------+
| docker  | btrfs  |                                     | 0       | CREATED |
+---------+--------+-------------------------------------+---------+---------+

现在该创建一个新的incus实例并将其命名为"docker-www-1"。以下是基于Debian 12的Incus实例的命令:

1
$ incus launch images:debian/12/cloud docker-www-1

想要Ubuntu Linux 24.04 Incus实例?尝试:

1
$ incus launch images:ubuntu/noble/cloud docker-www-1

想要Amazon Linux、Rocky Linux或Alpine Linux incus实例来运行Docker?这是可能的:

1
$ incus launch images:alpine/3.21/cloud docker-www-1

1
$ incus launch images:rockylinux/9/cloud docker-www-1

1
$ incus launch images:amazonlinux/2023 docker-www-1

使用AWS/GCP/Azure实例类型

您可以使用与AWS实例相同的大小创建和启动容器,以便在本地开发机器上测试和开发应用程序。例如,t2.xlarge(4 vCPU,16GiB RAM)如下,以在本地开发机器上模拟您的EC2基础设施(也支持GCP或Azure类型):

1
2
$ incus launch images:{distro_name}/{version} {container_name} -t aws:t2.xlarge
$ incus launch images:debian/12/cloud docker-www-1 -t aws:t2.xlarge

对于GCP/GCE(Google Cloud):

1
$ incus launch images:{distro_name}/{version} {container_name} -t gce:f1-micro

对于MS-azure云:

1
$ incus launch images:{distro_name}/{version} {container_name} -t azure:A5

除了AWS/GCP/Azure云提供商大小之外,您可以根据需要启动容器并限制其资源。例如,以下是如何将限制设置为两个vCPU和4092 MiB RAM的命令:

1
2
3
$ incus launch images:ubuntu/24.04 test \
--config limits.cpu=2 \
--config limits.memory=4092MiB

基于云提供商服务器或自定义规范轻松分配CPU和RAM限制的能力使Incus成为在本地开发机器上测试和开发应用程序的完美工具。这种灵活性有助于节省资金并促进更轻松的功能测试。让我们回到手头的示例,这里我坚持使用Debian Linux 12云镜像,以下是如何验证它:

1
$ incus list

输出:

1
2
3
4
5
+--------------+---------+-----------------------+------+-----------+-----------+
|     NAME     |  STATE  |         IPV4          | IPV6 |   TYPE    | SNAPSHOTS |
+--------------+---------+-----------------------+------+-----------+-----------+
| docker-www-1 | RUNNING | 10.147.164.177 (eth0) |      | CONTAINER | 0         |
+--------------+---------+-----------------------+------+-----------+-----------+

请记住,我默认使用btrfs作为存储驱动程序。但是,如果您不使用btrfs存储驱动程序,则按以下方式分配它。首先,在名为docker的存储下创建一个名为demovol的新卷:

1
2
$ incus storage volume create docker demovol
$ incus storage volume list docker

以下输出显示docker btrfs存储的’custom/demovol’:

1
2
3
4
5
+--------+---------+-------------+--------------+---------+
|  TYPE  |  NAME   | DESCRIPTION | CONTENT-TYPE | USED BY |
+--------+---------+-------------+--------------+---------+
| custom | demovol |             | filesystem   | 1       |
+--------+---------+-------------+--------------+---------+

按以下方式附加它:

1
$ incus config device add docker-www-1 docker disk pool=docker source=demovol path=/var/lib/docker

换句话说,您有一个需要btrfs存储空间的容器。此命令类似于将外部存储附加到您的容器。您告诉Incus从名为"docker"的btrfs存储中获取名为"demovol"的存储块,并将其在容器内的特定位置/var/lib/docker处提供给容器(“docker-www-1”)。按以下方式验证它:

1
$ incus config show docker-www-1

查找’devices’部分:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
architecture: x86_64
config:
  image.architecture: amd64
....
..
devices:
  docker:
    path: /var/lib/docker
    pool: docker
    source: demovol
    type: disk
ephemeral: false
...
..
stateful: false
description: ""

有关更多信息,请参阅如何在LXD(Linux容器)页面中添加或挂载目录。

最后,将security.nesting设置为true和其他属性,这允许在Incus容器实例中成功运行Docker:

1
2
3
$ incus config set docker-www-1 security.nesting=true \
security.syscalls.intercept.mknod=true \
security.syscalls.intercept.setxattr=true

其中设置是:

  • security.nesting=true:允许在Incus实例中运行Docker容器。
  • security.syscalls.intercept.mknod=true:允许mknod和mknodat Linux系统调用在Incus内安全地为Docker创建各种特殊文件。
  • security.syscalls.intercept.setxattr=true:允许setxattr Linux系统调用在Incus内安全地为Docker设置文件的扩展属性。

请注意,Incus容器无法加载Linux内核模块,因此根据您的Docker配置,您可能需要主机加载额外的Linux内核模块(设备驱动程序)。您可以设置容器所需的内核模块的逗号分隔列表。语法是:

1
2
$ incus config set {incus_container_name} linux.kernel_modules {module}
$ incus config set {incus_container_name} linux.kernel_modules {module1,module2,...}

您必须重新启动实例,输入:

1
$ incus restart docker-www-1

步骤2 - 在Incus容器中安装Docker

首先,登录到实例:

1
$ incus exec docker-www-1 bash

1
$ incus exec docker-www-1 sh

现在,您需要根据实例操作系统遵循常规的Docker安装说明。对于Debian Linux 12:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
$ sudo apt-get update
$ sudo apt-get install ca-certificates curl
$ sudo install -m 0755 -d /etc/apt/keyrings
$ sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
$ sudo chmod a+r /etc/apt/keyrings/docker.asc
$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

您使用的是Amazon Linux版本2吗?有关更多信息,请参阅如何在Amazon Linux 2上安装Docker。以下是如何验证您的Docker安装:

1
$ docker --version

输出:

1
Docker version 27.4.0, build bde2b89

步骤3 - 部署容器进行测试

让我们创建一个Apache Web服务器来提供静态网页index.html:

1
$ vim index.html

添加以下内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<!DOCTYPE html>
<html>
<head>
  <title>nixCraft's - Apache Docker Container Test</title>
</head>
<body>
  <h1>Hello from Apache Docker Server!</h1>
  <p>I'm running inside Incus instance.</p>
</body>
</html>

接下来创建Dockerfile:

1
$ vim Dockerfile

添加以下配置:

1
2
3
4
5
6
7
FROM httpd:latest

# Copy the index.html file to the Apache document root
COPY index.html /usr/local/apache2/htdocs/

# Expose port 80 to the outside world
EXPOSE 80

构建docker镜像:

1
# docker build -t test-apache-container .

以下命令从test-apache-container镜像运行容器,并将主机(Incus实例)上的TCP端口8080映射到容器中的端口80:

1
# docker run -d -p 8080:80 test-apache-container

使用curl命令测试它:

1
$ curl http://localhost:8080/

完成后,您可以停止容器。首先,列出所有正在运行的容器:

1
# docker ps -a

输出:

1
2
CONTAINER ID   IMAGE                   COMMAND              CREATED          STATUS          PORTS                                     NAMES
ea67ff7cb032   test-apache-container   "httpd-foreground"   10 minutes ago   Up 10 minutes   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   bold_fermi

您现在可以使用"CONTAINER ID"(如"ea67ff7cb032")或"NAME"(如"bold_fermi")来停止和删除它。例如:

1
# docker stop ea67ff7cb032

删除容器:

1
# docker rm ea67ff7cb032

删除镜像:

1
# docker rmi test-apache-container

使用新方法在Incus中设置Docker

最新版本的Incus支持直接运行Docker容器镜像。您至少需要Incus客户端/服务器版本6.3或更高版本:

1
$ incus version

输出:

1
2
Client version: 6.8
Server version: 6.8

此功能仍然是新的,有时可能无法按预期工作。因此,如前所述,我建议坚持使用传统方法。

首先,设置使用OCI镜像的服务器应用程序容器注册表,使用以下命令:

1
2
$ incus remote add docker https://docker.io --protocol=oci
$ incus remote

现在您可以从其镜像之一启动容器:

1
$ incus launch docker:hello-world --ephemeral --console

如何使用OCI Docker镜像运行MySQL服务器?尝试:

1
2
3
4
5
$ incus launch docker:mysql mysql-db \
-c environment.MYSQL_DATABASE=db_name_here \
-c environment.MYSQL_USER=db_user_name_here \
-c environment.MYSQL_PASSWORD=db_password_here \
-c environment.MYSQL_RANDOM_ROOT_PASSWORD=mysql_root_password_here

验证它:

1
$ incus list

现在就是全部内容。

总结

我更喜欢旧方法,因为自从LXD时代以来我一直在使用它,并且我知道如何使用它。新方法更容易,但有一些限制。我仍在探索这些。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计