玩命加载中 . . .

Ubuntu23下Docker部署


概述

很久没有碰Docker了,今天在VM下(基于Ubuntu23 Server)安装docker,记录一下。

安装Docker

使用如下脚本,一键部署docker

import os
import sys
import subprocess


# 检查当前用户是否是root用户
def is_root_user():
    print("  检查是否为root用户")
    return os.geteuid() == 0

# 尝试执行一个需要sudo权限的命令,判断是否具有sudo权限
def has_sudo_permission():
    print("  检查是否具有sudo权限")
    try:
        # 这里我们尝试更改一个只有root用户才能更改的系统文件的权限
        # 如果有sudo权限,这个命令会被sudo执行并成功更改权限
        # 注意:这是一个无害的命令,只是尝试更改文件的权限并不会真的创建文件
        subprocess.run(['sudo', 'chmod', '755', '/etc/passwd'], check=True,
                       stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        return True
    except subprocess.CalledProcessError:
        # 如果捕获到CalledProcessError异常,说明没有sudo权限
        return False

# 检查是否具有执行安装的权限
def check_root_privilege():
    print("\nStep1.检查当前用户是否有root权限")
    if not is_root_user() or not has_sudo_permission():
        print("Error: You must have root privileges to install Docker. Please run as root or use 'sudo'.")
        sys.exit(1)

# 执行命令并检查返回值
def run_command(command):
    try:
        subprocess.run(command, check=True)
    except subprocess.CalledProcessError as e:
        print(f"Error executing command '{' '.join(command)}': {e}")
        sys.exit(1)

# 主函数,安装Docker
def install_docker():
    # 检查当前用户是否是root用户
    check_root_privilege()
    
    # 更新软件包索引
    print('\nStep2.apt-get update')
    run_command(["sudo", "apt-get", "update"])
    
    # 安装Docker所需的依赖包
    print("\nStep3.安装Docker所需的依赖包")
    run_command(["sudo", "apt-get", "install", "-y", "apt-transport-https",
                 "ca-certificates", "curl", "gnupg", "lsb-release"])
    
    # 添加Docker的官方GPG密钥
    print("\nStep4.添加Docker的官方GPG密钥")
    try:
        # 使用Popen来执行管道命令
        process = subprocess.Popen(["curl", "-fsSL", "https://download.docker.com/linux/ubuntu/gpg"],
                                   stdout=subprocess.PIPE)
        # 将curl命令的输出通过管道传递给apt-key add命令
        gpg_key = process.communicate()[0].decode().strip()
        # 添加GPG密钥
        run_command(["echo", gpg_key, "|", "sudo", "apt-key", "add"])
    except subprocess.CalledProcessError as e:
        print(f"Error adding Docker GPG key: {e}")
        sys.exit(1)

    # 设置稳定的Docker仓库
    # 你需要根据你的系统版本替换LSB_RELEASE_OUTPUT变量的值
    print("\nStep5.设置稳定的Docker仓库")

    # 获取系统的LSB版本和发行版代号
    lsb_release_output = subprocess.check_output(['lsb_release', '-cs', '|', 'grep', '-v', 'No']).decode().strip()
    
    run_command(["sudo", "add-apt-repository", "deb [arch=amd64] https://download.docker.com/linux/ubuntu",
                 f"{lsb_release_output}", "docker", "stable"])

    # 移除错误的Docker仓库(如果已添加)
    run_command(["sudo", "rm", "-rf", "/etc/apt/sources.list.d/docker.list"])
    
    # 构造正确的Docker仓库URL
    docker_repository = f"https://download.docker.com/linux/ubuntu {lsb_release_output}"
    
    # 添加Docker的官方仓库到系统的sources.list文件
    run_command(["sudo", "add-apt-repository", " deb [arch=amd64] " + docker_repository + " docker-ce stable"])
    
    # 更新软件包索引
    run_command(["sudo", "apt-get", "update"])

    # 再次更新软件包索引
    print("\nStep6.再次更新软件包索引")
    run_command(["sudo", "apt-get", "update"])
    
    # 安装Docker Engine
    print("\nStep7.安装Docker Engine")
    run_command(["sudo", "apt-get", "install", "-y", "docker-ce", "docker-ce-cli", "containerd.io"])
    
    # 启动Docker服务
    print("\nStep8.启动Docker服务")
    run_command(["sudo", "systemctl", "enable", "docker"])
    run_command(["sudo", "systemctl", "start", "docker"])
    
    print("[Success]Docker has been successfully installed!")

if __name__ == "__main__":
    install_docker()

执行成功后,检查Docker是否被成功安装:

root@Service:~# docker ps
CONTAINER ID   IMAGE             COMMAND       CREATED        STATUS             PORTS     NAMES
root@Service:~#

出现如上信息,表明Docker成功安装。

安装docker-compose

前往官网https://github.com/docker/compose/releases,查看最新版本,比如v2.26.1,使用如下命令进行安装:

curl -L "https://github.com/docker/compose/releases/download/v2.26.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

安装后,执行docker-compose --version检查是否安装成功:

root@Service:~# docker-compose --version
Docker Compose version v2.26.1
root@Service:~# 

如上表示成功安装了docker-compose v2.26.1版本。

安装docker-machine

前往官网https://github.com/docker/machine/releases获取最新release版本号,比如v0.16.2,执行如下命令进行安装:

base=https://github.com/docker/machine/releases/download/v0.16.2 &&
curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine &&
mv /tmp/docker-machine /usr/local/bin/docker-machine &&
chmod +x /usr/local/bin/docker-machine

检查安装效果:

root@Service:~# docker-machine --version
docker-machine version 0.16.2, build bd45ab13
root@Service:~# docker-machine ls
NAME   ACTIVE   DRIVER   STATE   URL   SWARM   DOCKER   ERRORS
root@Service:~# 

docker-machine 使用

接下来通过 virtualbox 来介绍 docker-machine 的使用方法。其他云服务商操作与此基本一致,具体可以参考每家服务商的指导文档。

说明:

请从https://www.virtualbox.org/wiki/Downloads下载并安装virtualbox,并设置环境变量。

比如我的环境是Ubuntu 23,直接 apt-get install virtualbox 进行安装。

列出可用的机器

root@Service:~# docker-machine ls
NAME   ACTIVE   DRIVER   STATE   URL   SWARM   DOCKER   ERRORS
root@Service:~# 

显示为空。

创建可用的机器

创建一台名为 Gavin 的机器:

docker-machine create --driver virtualbox Gavin

创建过程如下:

root@Service:~# docker-machine create --driver virtualbox Gavin
Creating CA: /root/.docker/machine/certs/ca.pem
Creating client certificate: /root/.docker/machine/certs/cert.pem
Running pre-create checks...
Error with pre-create check: "VBoxManage not found. Make sure VirtualBox is installed and VBoxManage is in the path"
root@Service:~# 
  • –driver:指定用来创建机器的驱动类型,这里是 virtualbox。

这个时候再次列出可用机器:

root@Service:~# docker-machine create --driver virtualbox Gavin
Running pre-create checks...
(Gavin) No default Boot2Docker ISO found locally, downloading the latest release...
(Gavin) Latest release for github.com/boot2docker/boot2docker is v19.03.12
(Gavin) Downloading /root/.docker/machine/cache/boot2docker.iso from https://github.com/boot2docker/boot2docker/releases/download/v19.03.12/boot2docker.iso...
(Gavin) 0%....10%....20%....30%....40%....50%....60%....70%....80%....90%....100%
Creating machine...
(Gavin) Copying /root/.docker/machine/cache/boot2docker.iso to /root/.docker/machine/machines/Gavin/boot2docker.iso...
(Gavin) Creating VirtualBox VM...
(Gavin) Creating SSH key...
(Gavin) Starting the VM...
(Gavin) Check network to re-create if needed...
(Gavin) Found a new host-only adapter: "vboxnet0"
Error creating machine: Error in driver during machine creation: Error setting up host only network on machine start: /usr/bin/VBoxManage hostonlyif ipconfig vboxnet0 --ip 192.168.99.1 --netmask 255.255.255.0 failed:
VBoxManage: error: Code E_ACCESSDENIED (0x80070005) - Access denied (extended info not available)
VBoxManage: error: Context: "EnableStaticIPConfig(Bstr(pszIp).raw(), Bstr(pszNetmask).raw())" at line 252 of file VBoxManageHostonly.cpp

这里报错了,提示权限问题,暂时没解决掉,先放着吧。

常见错误

执行docker-compose up提示’services must be a mapping’

root@Service:~/composetest# docker-compose up
services must be a mapping
root@Service:~/composetest# 

错误信息 “services must be a mapping” 表示 docker-compose 命令无法执行,因为在执行过程中没有找到正确格式的 docker-compose.yml 文件,或者该文件格式不正确。对于YML文件,注意如下细节:

  • 缩进问题:YAML 文件非常依赖正确的缩进,且只接受空格作为缩进字符,不接受制表符(Tab)。请确保每一级缩进都使用了两个或更多的空格,并且层级结构保持一致。

  • 行尾的空格:YAML 文件中的每一行末尾都不能有任何额外的字符,包括空格。

进入容器报错’stat /bin/bash: no such file or directory: unknown’

root@Service:~# docker exec -it 085bdc5ed931 /bin/bash
OCI runtime exec failed: exec failed: unable to start container process: exec: "/bin/bash": stat /bin/bash: no such file or directory: unknown
root@Service:~# 

解决方法:更换shell类型:

root@Service:~# docker exec -it 085bdc5ed931 /bin/bash
OCI runtime exec failed: exec failed: unable to start container process: exec: "/bin/bash": stat /bin/bash: no such file or directory: unknown
root@Service:~# docker exec -it 085bdc5ed931 /bin/sh
/data # 
/data # 
/data # cat /etc/shells 
# valid login shells
/bin/sh
/bin/ash
/data # 

我们还可以通过echo $SHELL 命令来查看当前使用的Shell类型。

下面我们进行一些常见Shell的讲解:
(1) BourneShell(sh):是由AT&T Bell实验室的 Steven Bourne为AT&T的Unix开发的,它是Unix的默认Shell,也是其它Shell的开发基础。Bourne Shell在编程方面相当优秀,但在处理与用户的交互方面不如其它几种Shell。

(2) BourneAgain Shell (即bash):是自由软件基金会(GNU)开发的一个Shell,它是Linux系统中一个默认的Shell。Bash不但与Bourne Shell兼容,还继承了C Shell、Korn Shell等优点。

(3) ash:ash Shell是由Kenneth Almquist编写的,是Linux 中占用系统资源最少的一个小Shell,它只包含24个内部命令,因而使用起来很不方便。

(4) CShell(csh):是加州伯克利大学的Bill Joy为BSD Unix开发的,共有52个内部命令,与sh不同,它的语法与C语言很相似。它提供了Bourne Shell所不能处理的用户交互特征,如命令补全、命令别名、历史命令替换等。但是,C Shell与BourneShell并不兼容。该Shell其实是指向/bin/tcsh这样的一个Shell,也就是说,csh其实就是tcsh。

(5) KornShell(ksh):是AT&T Bell实验室的David Korn开发的,共有42 条内部命令,它集合了C Shell和Bourne Shell的优点,并且与Bourne Shell向下完全兼容。Korn Shell的效率很高,其命令交互界面和编程交互界面都很好。

(6) zch:是Linux 最大的Shell之一,由Paul Falstad完成,共有84 个内部命令。如果只是一般的用途,没有必要安装这样的Shell。

注释:bash是 Bourne Again Shell 的缩写,是linux标准的默认shell ,它基于Bourne shell,吸收了C shell和Korn shell的一些特性。bash完全兼容sh,也就是说,用sh写的脚本可以不加修改的在bash中执行。

docker-machine create 报错 E_ACCESSDENIED (0x80070005)

(Gavin) Found a new host-only adapter: "vboxnet1"
Error creating machine: Error in driver during machine creation: Error setting up host only network on machine start: /usr/bin/VBoxManage hostonlyif ipconfig vboxnet1 --ip 192.168.99.1 --netmask 255.255.255.0 failed:
VBoxManage: error: Code E_ACCESSDENIED (0x80070005) - Access denied (extended info not available)
VBoxManage: error: Context: "EnableStaticIPConfig(Bstr(pszIp).raw(), Bstr(pszNetmask).raw())" at line 252 of file VBoxManageHostonly.cpp

解决方法:

暂时未找到有效解决方法,先搁置。


文章作者: Gavin Wang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Gavin Wang !
  目录