Docker 新人入门踩坑

in Program with 0 comment
市面上的 Docker 入门教程非常的多,尤其推荐 Docker Practice,我就是看着这本书入门的,但是在我看来这对新人还是有一定的门槛的有几点我踩到坑里了。接下来会来讲一讲我入门踩到的坑以及 Docker 的一些基本使用。

提要

要先声明一下前提:我在使用 Docker 期间一直是在单机上部署

我踩到的坑

  1. 将容器视为一个进程。由于是在单机上部署,之前也没有用过虚拟机,所以一直还将容器视为一个进程
  2. 容器的网络,容器之间无法互通
  3. 挂载路径上去后请求总是 404

其实这几个坑都是因为自己的观念没有转变的问题,对容器的认知错误的的停留在进程的层面。

所以在开始,各位一定要树立好观点:一个容器 = 一台独立的机器。这样可能不太严谨,但是在入门阶段应该没有大碍。

Docker 的基本使用

这部分主要涉及 Docker 单独容器的使用,熟练掌握基本的 Docker 命令。

Docker 容器互联

这部分要聊一下容器之间配合的相关事情,当然还有里面的坑。

Docker 基本使用

什么是 Docker

能看到这篇文章的应该对 Docker 有了基本的认知,在此概述一下:Docker 是 Linux 容器技术的封装,它就像 Java 一样,一次编译,到处运行,构建好容器后,只要是支持 Docker 的平台,都能直接跑起来,不需要做其他的配置。

总之就是用起来很爽就是了,像我们这种穷逼,只能买得起特价服务器,到期后就要迁移服务器,有了 Docker 后,服务器到期了只要把数据备份了,然后到新服务器镜像跑起来就直接能用。

安装

建议参考 Docker Practice 里面有非常详细的资料。国内设置镜像,一般服务器不需要,我们本地测试的时候可能会需要,我在这里给出几个可用的镜像站:

// 官方的中国加速镜像
https://registry.docker-cn.com
// 网易的
https://hub-mirror.c.163.com

基本使用

基本的容器启动,停止这些看 Docker Practice 即可,这里主要要讲一下挂载的概念。

挂载

Docker 容器我们希望可以解决环境配置的问题,那么自然也需要“无状态”,什么是无状态呢?就是我们应用程序产生的数据,就不要放在 Docker 里面了,比如数据库的数据、nginx 的静态网站等等。

既然 Docker 容器内不能放数据,那么数据就只能放在宿主机上了,这就需要将我们将容器内的路径映射到宿主机上,这其实跟端口映射是一样的。

VOLUME: 在 Dockerfile 里用这个命令可以声明一个匿名卷,声明在运行时没有可以挂载路径到这个卷上(其实也是也路径)。但是如果镜像中没有声明匿名卷,我不清楚能不能在运行时挂载,我没有尝试过。

运行时挂载我这里给个 demo:

docker run -d -v mydata:/data xxxx

这个命令表示将宿主机的 mydata 挂载到容器的 /data 位置。

注意:这里有坑了,挂载了以后,容器内应用程序的配置文件里的路径还是容器内的路径,比如说挂载了宿主机 /opt/nginx/html 到容器的 /usr/share/nginx/html 路径(典型的 nginx 容器挂载),那么在配置 nginx 的时候,记得静态网站的资源路径在 /usr/share/nginx/html 而不在 /opt/nginx/html我开始的时候因为这个 404 了好久。

而且挂载路径的时候可以指定权限的,比如:

docker run -d -v mydata:/data:ro xxxx

就是只读。

docker-compose

docker-compose 的教程依旧推荐 Docker Proctice,只是它里面也不太详细,所以我也是皮毛,但是在这里我要说一句安装。

在 Ubunut 里安装 docker-compose 不能直接用 apt-get 安装,这样虽然方便,但是版本太低了,建议直接去 GitHub 下载可执行文件,详细的操作都在 Docker Proctice

容器互联

这部分其实也是基本使用,但是也坑我比较久,所以就提高一下优先级。

Docker 的优势之一就是隔离环境,所以我们千万不能把多个进程放在一个容器内,这样会导致耦合太强,扩展性不高。建议一个容器跑一个进程。

一般的应用程序需要:nginx,mysql,自己的服务。这样看来至少需要三个进程了,按照 Docker 的原则就需要三个容器。那么三个容器要怎么配合呢?

注意:这里我又踩坑了!我还是那个原因,将容器视为进程,导致连接不上。

这里有几个坑:

  1. 容器映射到宿主机的端口,其他容器不能直接访问(访问宿主机的 IP 除外)。
  2. 容器之间如果没有 link 或者共用 network,那么容器之间不能互相访问(访问映射到宿主机的 IP 除外)。
  3. 容器之间 link 或者共用 network 后,直接访问容器内部暴露的端口即可,不要访问映射到宿主机的端口。

当然除了坑之外也要说几点心得

  1. 如果使用 docker-compose,那么默认里面的容器就会处于同一个 network 下
  2. 同一个 network 下的容器,可以打一个并不严谨的比喻:一堆机器连着同一个WiFi,这时候可以直接通过 ip 访问,但是这样扩展性太低,我们可以给容器起别名,可以直接通过 别名:端口 访问。

后记

目前我的 Docker 踩坑到此为止了(其实是自己蠢),后续还会持续探索,持续踩坑进步。

生命不止,折腾不息

Responses