记录Docker使用过程中遇到的难点和问题

20,428次阅读
没有评论

共计 4710 个字符,预计需要花费 12 分钟才能阅读完成。

重新理解

1.Docker 容器

Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。

被打包的程序可以是一个操作系统,也可以是 Nginx 应用,也可以是 PHP 等任意一种“程序”,打包之后的镜像可以在任意一台安装了 Docker 的主机上,完美的运行。

多个容器可以和不使用容器的应用一样,相互进行协作、通信,例如基于 Docker 的 lnmp 环境可以由 nginx、mysql、php 三个容器进行实现。同时可以通过 docker composer 进行编排。

2. 停止容器 

容器在创建之后,只要不删除就一直存在,并且保持着停止前的状态。

镜像就类似我们常用的.exe 文件,执行之后就产生了这个程序的进程,容器就类似这个进程,一个镜像可以被同时运行很多次,产生多个容器。

3. 修改容器端口映射、挂载目录

容器一旦生成,没有一个命令可以直接修改。通常间接的办法是,保存镜像,再创建一个新的容器,在创建时指定新的端口映射。

使用主机网络时,- p 指定的端口映射将会失效。使用主机网络时不需要进行端口映射。

# 容器内访问 /home 会链接到主机的 /home/lnmp 目录
docker run -idt -v /home/lnmp:/home --network host centos:centos7 /bin/bash
# window 系统映射目录时 /D/path 代表 D 盘

# window 测试
docker run -idt -v /F/swoole:/home --network bridge -p 6666:8081 phpswoole/swoole:latest /bin/bash

window 本地目录挂载

window 遇到挂载本地目录不生效的问题,而且 run 之后也不报错,最后将挂载目录放到了用户目录下面生效了。换了一台电脑测试,发现挂载到任意位置都可以,具体原因有待深究。

window 下启动容器需要映射端口,host 模式无法正常使用

4. 关于容器

容器运行之后,会产生一个完整的服务器文件目录结构,针对运行的应用的不同,这个容器所带有的功能也不同(主要区别可 exec 进行命令行后测试),例如一个 centos 应用具有操作系统的大部分功能命令,而 Nginx 应用容器只能操作 Nginx;

5. 修改 apt 安装源

将文件在本地创建,然后 mv 替换容器内的源文件即可,。

deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse

#移动替换
mv sources.list /etc/apt/sources.list

6.apt 无法更新

报错,提示连接不上镜像源,首先考虑 DNS 的问题。

# 指定 DNS
docker run -idt -v /C/swoole:/home --network bridge -p 6666:8081  --dns 114.114.114.114 phpswoole/swoole:latest  /bin/bash

7.window Docker

docker 是运行在 Linux 上的,在 Windows 中运行 docker,实际上还是在 Windows 下先安装了一个 Linux 环境,然后在这个系统中运行的 docker。

也就是说,服务中使用的 localhost 指的是这个 Linux 环境的地址,而不是我们的宿主环境 Windows10。

提示

主机网络驱动程序仅适用于 Linux 主机,并且不支持 Docker for Mac,Docker for Windows 或 Docker EE for Windows Server。(网络查找得知,未见到官方文档)

8. 容器内安装软件包

centos 的 yum,ubuntu 的 apt-get

apt-get update
apt-get install  procps
apt-get install inetutils-ping

9. 解决 docker 没有中文包的问题

# apt-get -y install locales
# sed -ie 's/# zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/g' /etc/locale.gen 
# locale-gen zh_CN.UTF-8

Docker 空间清理 

突然发现被 rm 的容器仍然占用着存储空间,prune 命令用来删除不再使用的 docker 对象。

# 删除所有未被 tag 标记和未被容器使用的镜像:
$ docker image prune

# 删除所有未被容器使用的镜像:
$ docker image prune -a

# 删除所有停止运行的容器:
$ docker container prune

# 删除所有未被挂载的卷:
$ docker volume prune

#删除所有网络:
$ docker network prune

# 删除 docker 上述所有
$ docker system prune

Docker 容器间的通信

参考:https://blog.51cto.com/u_15917617/5953332

docker 容器之间是互相隔离的,这是容器设计的初衷,造成了相互之间不能互相访问,但是我们有时候会在 docker 中启动多个容器,而且相互之间还需要相互通信,docker 提供以下三种方式:

1. 虚拟 IP 

Dokcer 在安装的时候,会默认创建一个内部的桥接网络 docker0,每创建一个容器分配一个虚拟网卡,容器之间可以根据 ip 互相访问,进入 docker,可以看到 IP 地址:

[root@192 monitor-demo]# ifconfig
docker0: flags=4099  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
        ether 02:42:60:88:39:75  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

在 docker 里安装的容器都会默认分配一 IP 地址,容器之间可以根据 IP 地址相互通信。使用 IP 的缺点很明显,首先容器相互之间获取 IP 困难,再者容器重启后 IP 地址会变化,这样对性能要求较高的服务就不可行。

2. 容器名称(link)

运行容器的时候加上参数 link。

# 运行第一个容器
​​​docker run -it --name nginx-A docker.io/nginx:latest​​​ 
# 运行第二个容器
​​docker run -it --name centos-2 --link nginx-A:nginx-A-Alias docker.io/nginx:latest​​

这样在第二个容器里可以根据 ​​nginx-A-Alias + 端口号​​​·的形式访问。这种方法解决了 IP 地址变化的问题,但是这种方法对于容器的顺序有要求。如果要相互访问,就有麻烦了。

3. bridge 网络 

# 查看网络

$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
f6507cb66afc   bridge    bridge    local
82f1edf2310e   host      host      local
7408ad904d75   none      null      local
# 创建网络

$ docker network create local
b515b6d4abb2db310968ca8bbc842fcdead69f59af2ae8e2040af9064cf51f28
# 运行容器

$ docker run -idt -v /C/swoole:/home --name swoole --network local -p 83:80 --network-alias swoole ca3579da08fe /bin/bash 
$ docker run -idt --name redis --network local -p 85:6379 --network-alias redis 3c3da61c4be0 /bin/bash 

这样,两个 docker 就可以通过 bridge 网络通过使用这用方式访问 <网络别名>:<服务端口号> 通信了。使用这种方法,自定义网络,因为使用的是网络别名,可以不用顾虑 ip 变化以及 docker 启动顺序的问题,只要连接到 docker 内部 bright 网络即可互访。bridge 也可以建立多个,用于隔离在不同的网段内的应用程序(docker)。

进行通信时,要使用容器的端口,而不是映射的宿主机端口

配置 DNS 

可以在宿主机的 /etc/docker/daemon.json 文件中增加以下内容来设置全部容器的 DNS

{
  "dns" : [
    "114.114.114.114",
    "8.8.8.8"
  ]
}

设置后,启动容器的 DNS 会自动配置为 114.114.114.114 和 8.8.8.8。

配置完,需要重启 docker 才能生效。

查看容器的 DNS 是否生效可以使用以下命令,它会输出容器的 DNS 信息:

$ docker run -it --rm  ubuntu  cat etc/resolv.conf

如果只想在指定的容器设置 DNS,则可以使用以下命令:

$ docker run -it --dns=114.114.114.114 ubuntu

–dns=IP_ADDRESS:添加 DNS 服务器到容器的 /etc/resolv.conf 中,让容器用这个服务器来解析所有不在 /etc/hosts 中的主机名。

Docker 性能损耗、优化

暂时没找到相关的资料,需要自己实际进行测试。

1. 性能

IO、网络,对于 IO 可以把容器的应用运行时 IO 的目录挂载到容器的外部目录。对于网络可以指定使用服务器本身的网络 --network host;

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于2024-09-10发表,共计4710字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)