【前端运维】打通任督二脉!(linux + docker)

lxf2023-05-04 13:48:02

前言

前端运维最基本的要求就是你在单机的架构下能够给自己的前端团队提供各种服务,比如CI/CD、前端监控/日志服务等等。

(中小型公司你做前端负责人这个水平是要有的,大公司都有完善的系统自动发布,但是起码你要会写自己会配比如ng脚本,dockerfile等等吧,以前我在滴滴的时候,虽然有统一部署平台,负责人还是要写这些配置的)

注意点

一定要注意,下面所有内容,知道有这个命令就行了,不需要背下来,因为你真的用多了,自然就记下来了,而且我们前端面试几乎遇不到下面的内容(除了在B端的前端架构组),所以不要有任何压力。

觉得,这我不知道,那个也不知道,没啥的

开始

首先解释下一般情况,前端需要把运维的能力拓展到什么程度就够了?

先说结论,基本的单机架构能hold住,就可以了。

在此之前我们要了解一下大型网站架构的历程,就可以清晰的定位到一个基本应用所需要的架构体系,然后找出最简单的架构(就算是掌握最简单架构能力,也完全可以在中小公司做全栈了)

大型网站架构演化发展历程(有10个阶段,但前端掌握到第4个阶段就差不多了)

1. 初始阶段的网站架构

大型网站都是从小型网站发展而来,网站架构也是一样,是从小型网站架构逐步演化而来。小型网站最开始没有太多人访问,只需要一台服务器就绰绰有余,这时的网站架构如下图所示:

【前端运维】打通任督二脉!(linux + docker)

应用程序、数据库、文件等所有资源都在一台服务器上。通常服务器操作系统使用Linux,应用程序使用Nodejs开发、然后使用docker部署、数据库使用MySQL,汇集各种免费的开源软件以及一台廉价服务器就可以开始网站的发展之路了。

2. 应用服务和数据服务分离

随着网站业务的发展,一台服务器逐渐不能满足需求:越来越多的用户访问导致性能越来越差,越来越多的数据导致存储空间不足。这时就需要将应用和数据分离。应用和数据分离后整个网站使用3台服务器:应用服务器、文件服务器和数据库服务器。这 3 台服务器对硬件资源的要求各不相同:

  • 应用服务器需要处理大量的业务逻辑,因此需要更快更强大的CPU;
  • 数据库服务器需要快速磁盘检索和数据缓存,因此需要更快的磁盘和更大的内存
  • 文件服务器需要存储大量用户上传的文件,因此需要更大的硬盘。

此时,网站系统的架构如下图所示:

【前端运维】打通任督二脉!(linux + docker)

应用和数据分离后,不同特性的服务器承担不同的服务角色,网站的并发处理能力和数据存储空间得到了很大改善,支持网站业务进一步发展。但是随着用户逐渐增多,网站又一次面临挑战:数据库压力太大导致访问延迟,进而影响整个网站的性能,用户体验受到影响。这时需要对网站架构进一步优化

3. 使用缓存改善网站性能

网站访问的特点和现实世界的财富分配一样遵循二八定律:80% 的业务访问集中在20% 的数据上。既然大部分业务访问集中在一小部分数据上,那么如果把这一小部分数据缓存在内存中,就可以减少数据库的访问压力,提高整个网站的数据访问速度,改善数据库的写入性能了。 网站使用的缓存可以分为两种:缓存在应用服务器上的本地缓存和缓存在专门的分布式缓存服务器上的远程缓存。

  • 本地缓存的访问速度更快一些,但是受应用服务器内存限制,其缓存数据量有限,而且会出现和应用程序争用内存的情况。
  • 远程分布式缓存可以使用集群的方式,部署大内存的服务器作为专门的缓存服务器,可以在理论上做到不受内存容量限制的缓存服务。

【前端运维】打通任督二脉!(linux + docker)

使用缓存后,数据访问压力得到有效缓解,但是单一应用服务器能够处理的请求连接有限,在网站访问高峰期,应用服务器成为整个网站的瓶颈。

  • 使用应用服务器集群改善网站的并发处理能力
  • 使用集群是网站解决高并发、海量数据问题的常用手段。当一台服务器的处理能力、存储空间不足时,不要企图去更换更强大的服务器,对大型网站而言,不管多么强大的服务器,都满足不了网站持续增长的业务需求。这种情况下,更恰当的做法是增加一台服务器分担原有服务器的访问及存储压力。%20对网站架构而言,只要能通过增加一台服务器的方式改善负载压力,就可以以同样的方式持续增加服务器不断改善系统性能,从而实现系统的可伸缩性。应用服务器实现集群是网站可伸缩架构设计中较为简单成熟的一种,如下图所示:

    通过负载均衡调度服务器,可以将来自用户浏览器的访问请求分发到应用服务器集群中的任何一台服务器上,如果有更多用户,就在集群中加入更多的应用服务器,使应用服务器的压力不再成为整个网站的瓶颈。

    大型网站架构演化发展历程总共有10个阶段(阿里技术专家李智慧定义的),目前来看,前端同学掌握到第4个阶段完全可以说是不错了。

    到第4个阶段,其中涉及到哪些技术:

    • Linux基础命令
    • nginx负载均衡
    • Nodejs或者其他语言的后端服务,比如我会使用go语言
    • 缓存服务:redis
    • 关系型数据库:mysql
    • 容器技术: docker
    • 容器编排: k8s
    • 串联这些技术,CI/CD(github\gitlab)

    所以本文会列出:

    • Linux基础命令
    • docker / docker-compose的内容

    linux基础命令

    以下是精简版,浓缩的常用linux命令,基本上满足我们上面提到的第4阶段需要掌握的基础命令。

    ls

    • 查询目录中的内容

    • ls [选项] [文件或者目录]

    • 选项

      • -a 显示所有文件,包括隐藏文件
      • -l 显示详细信息
    • 默认当前目录下的文件列表

    文件处理命令

    mkdir

    • 建立目录 make directory

    • mkdir -p [目录名]

    cd

    • 切换所在目录 change directory

    • cd [目录]

      • ~ 家目录
      • 家目录
        • 上次目录
      • . 当前目录
      • .. 上级目录
    • 按TAB键可以补全命令和目录

    pwd

    • 显示当前目录 pwd

    rmdir

    • 删除目录 remove empty directory
    • rmdir [目录名]

    rm

    • 删除文件或者目录 remove

    • rm [文件或者目录]

      • -r 删除目录
      • -f 强制删除
    • rm -rf 文件或者目录] 递归强制删除所有目录

    cp

    • copy 复制命令

    • copy [源文件或者目录] [目标文件]

      • -r 复制目录,默认是复制文件

    mv

    • 移动文件或者改名 move
    • mv [源文件或者目录] [目标文件]

    find

    • 文件搜索命令
    • find [搜索范围] [搜索条件]
    按名称搜索
    • 避免大范围的搜索,会非常消耗系统资源

      find / -name aaa.log
      
    通配符
    • find是在系统当中搜索符合条件的文件名,如果需要匹配,使用通配符匹配,通配符是完全匹配

    • 通配符

      • * 匹配任意内容
      • ? 匹配任意一个字符
      • [] 匹配任意一个中括号内的字符
    find . -name "ab[cdef]"
    
    grep
    • 在文件当中匹配符合条件的字符串

    • grep "10" access.log

      • -i 忽略大小写
      • -v 排除指定字符串
    • find命令,在系统当中搜索符合条件的文件名,如果需要匹配,使用通配符匹配,通配符是完全匹配

    • grep命令 在文件当中搜索符合条件的字符串,如果需要匹配,使用正则表达式进行匹配,正则表达式时包含匹配

    tar

    • 打包命令

    • tar -cvf 打包文件名 源文件

      • -c 打包
      • -v 显示过程
      • -f 指定打包后的文件名
    tar -cvf book.tar book
    
    • x 解打包

      tar -xvf book.tar
      

    df

    • df命令是linux系统中的磁盘空间状况命令,全称是"Disk Free",即磁盘剩余空间。该命令可以显示系统中每个文件系统的总大小、已用空间、可用空间等信息。

    通常使用格式如下:

    df [options] [filesystems]
    

    常用的选项有:

    • -h 以易读的方式显示,如G、M、K等单位

    例如:

    df -h
    

    输出结果类似于:

    Filesystem      Size  Used Avail Use% Mounted on
    /dev/sda1        30G   15G   14G  51% /
    devtmpfs        7.8G     0  7.8G   0% /dev
    

    ps

    • PS 命令是一种用于查看系统中正在运行的进程的工具,它可以帮助我们诊断系统问题、查看进程的状态和信息。

    常用的 PS 命令选项:

    • -aux:显示所有进程的详细信息,包括每个进程的用户、PID、CPU 和内存使用情况等。

    举个例子

    ps -aux 命令会显示出当前系统中所有进程的详细信息。下面是输出结果中一般包含的字段:

    [root@6be150f8f5ce /]# ps -aux
    
    USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    
    root         1  0.0  0.0  11704  2544 ?        Ss   02:35   0:00 /bin/bash
    
    root        15  0.2  0.0  11844  2916 pts/0    Ss   02:36   0:00 /bin/bash
    
    root        30  0.0  0.0  51748  3492 pts/0    R+   02:36   0:00 ps -aux
    
    • USER:进程所属的用户名。
    • PID:进程的唯一标识符,称为进程 ID。
    • %CPU:该进程占用的 CPU 百分比。
    • %MEM:该进程占用的物理内存的百分比。

    主要了解以上4个即可。

    touch

    • touch 命令是一个在 Unix 和 Linux 系统中常用的命令,用于创建空文件或更新文件的时间戳。

    使用方法

    • touch filename:如果文件不存在,则创建一个新文件,如果文件已存在,则更新该文件的最后访问时间和最后修改时间。

    例如:

    $ touch test.txt
    

    这将在当前目录下创建一个名为 test.txt 的空文件。

    sed

    • sed 命令是一种强大的流编辑器,用于在不打开文件的情况下在文本文件中执行替换操作。 追加:
    sed '3,5a\the end' sed.txt 在35末尾追加“the end”
    

    插入:

    sed '1i\begin' sed.txt  在第一行前插入一行“begin”
    

    替换:

    # 批量替换IP地址
    sed -r 's/192.168.0.([0-9]{1,2})/172.16.0.\1/g' sed.txt
    

    删除:

    sed -e '2d' sed.txt  删除第2

    chmod

    • 这里主要涉及的知识是文件权限,比如你新建一个文件,别的用户是没法执行的,改写也不行,这是为什么?有兴趣的同学可以自己网上搜相关知识点。这里只是简单介绍chmod的命令。

    例如,要赋予当前用户的文件file.txt可读写权限,可以使用以下命令:

    chmod u+rw file.txt
    

    配置网卡

    会有不同,一般都在network-scripts目录下 # vim /etc/sysconfig/network-scripts/ifcfg-ens34

    • 下面是配置文件(配置文件里最好不要有汉字)
    TYPE=Ethernet    # 网卡类型:为以太网
    PROXY_METHOD=none    # 代理方式:关闭状态
    BOOTPROTO=dhcp  # 设置网卡获得ip地址的方式,可能的选项为static(静态),dhcp(dhcp协议)或bootp(bootp协议).
    DEFROUTE=yes        # 默认路由:是, 不明白的可以百度关键词 `默认路由`
    IPV4_FAILURE_FATAL=no     # 是不开启IPV4致命错误检测:否
    IPV6INIT=yes         # IPV6是否自动初始化: 是[不会有任何影响, 现在还没用到IPV6]
    IPV6_AUTOCONF=yes    # IPV6是否自动配置:是[不会有任何影响, 现在还没用到IPV6]
    IPV6_DEFROUTE=yes     # IPV6是否可以为默认路由:是[不会有任何影响, 现在还没用到IPV6]
    IPV6_FAILURE_FATAL=no     # 是不开启IPV6致命错误检测:否
    IPV6_ADDR_GEN_MODE=stable-privacy   # IPV6地址生成模型:stable-privacy [这只一种生成IPV6的策略]
    NAME=ens34     # 网卡物理设备名称  
    UUID=8c75c2ba-d363-46d7-9a17-6719934267b7   # 通用唯一识别码,没事不要动它,否则你会后悔的。。
    DEVICE=ens34   # 网卡设备名称, 必须和 `NAME` 值一样
    ONBOOT=no #系统启动时是否设置此网络接口,设置为yes时,系统启动时激活此设备 
    IPADDR=192.168.103.203   #网卡对应的ip地址
    PREFIX=24             # 子网 24就是255.255.255.0
    GATEWAY=192.168.103.1    #网关  
    DNS1=114.114.114.114        # dns
    HWADDR=78:2B:CB:57:28:E5  # mac地址
    

    这些参数其实跟你的计算机网络基础有关系,都是一些概念,可能很多人连以太网都不知道是啥,这就需要你学习基本的计算机网络知识了。

    yum包管理

    • 我们不需要了解细节,主要掌握yum-config-manager这个工具来配置安装包即可 yum-config-manager 是一个用于管理 yum 配置的命令行工具,可用于修改 yum 源,开启或关闭某些源,或查询 yum 配置信息。

    以下是常用的几个用法示例:

    查看 yum 源列表:

    yum-config-manager --list
    

    开启某个源:

    yum-config-manager --enable repository-name
    

    其中,repository-name 是源的名称。

    关闭某个源:

    yum-config-manager --disable repository-name
    

    其中,repository-name 是源的名称。

    比较重要的是如何增加一个yum源,比如你下载docker镜像,基础的yum源里是没有下载地址的,所以你需要增加一个源。

    使用 yum-config-manager 增加 yum 源的步骤如下:

    1. 创建一个源配置文件,如 newrepo.repo
    sudo nano /etc/yum.repos.d/newrepo.repo
    
    1. 在配置文件中添加源信息:
    [newrepo]
    name=new repository
    baseurl=http://example.com/repo
    gpgcheck=0
    enabled=1
    
    1. 使用 yum-config-manager 命令来启用新源:
    sudo yum-config-manager --enable newrepo
    

    其中,newrepo 是源的名称。

    现在,你就可以使用 yum 从新源安装软件包了。

    注意:源的名称必须与配置文件的名称一致。

    ssh 远程连接工具

    • SSH (Secure Shell) 是一种加密的远程登录协议,通常用于远程服务器的管理。比如你买了一个腾讯云或者其他云服务器,就可以在自己的windows或者mac电脑里用ssh登录

    常用 SSH 命令:

    • ssh 用户名@主机地址:连接到远程主机。

    常用格式:

    ssh [user@]hostname [command]
    

    systemctl

    这是管理linux服务的命令,比如使用docker服务,如何控制它的启动和停止呢?一般centos7是靠systemctl命令实现的。

    以下是使用systemctl的一些示例:

    1. 启动一个服务:
    sudo systemctl start [service-name]
    
    1. 停止一个服务:
    sudo systemctl stop [service-name]
    
    1. 重启一个服务:
    sudo systemctl restart [service-name]
    

    awk

    awk,sed这些命令其实都非常复杂,但是我们掌握的是最最最基础的语法就差不多了,因为复杂的逻辑,自己写node脚本就行了。

    在此,我们仅介绍awk筛选列的功能。

    awk中,可以使用以下语法来筛选某一列的内容:

    awk '{print $N}' [input-file]
    

    其中,N是要筛选的列的编号,从1开始计数。

    例如,如果有一个名为data.txt的文件,其内容如下:

    apple orange banana
    red green blue
    dog cat bird
    

    要仅打印第二列(orangegreencat),可以使用以下命令:

    awk '{print $2}' data.txt
    

    输出结果如下:

    orange
    green
    cat
    

    awk中,每一行都被视为一个记录,并且每一列都被视为该记录的一个字段。因此,通过使用$N语法可以访问每一列的数据

    netstat

    "netstat",用于显示网络连接、路由表、接口统计信息。

    以下是"netstat"的一些最常用选项:

    • -t:仅显示TCP套接字
    • -u:仅显示UDP套接字
    • -l:仅显示监听套接字

    例如:显示UDP端口号的使用情况

    mengxiang@mengxiangde ~ % netstat -t 
    
    Active Internet connections
    
    Proto Recv-Q Send-Local Address          Foreign Address        (state)    
    
    tcp4       0      0  10.8.41.25.63294       52.231.30.137.https    ESTABLISHED
    
    tcp4       0      0  localhost.450         localhost.6223        ESTABLISHED
    
    

    注意:"netstat"已在许多现代Linux分发版中不再被支持,被"ss"或"ip"命令代替,但"netstat"仍然广泛使用。

    cat

    • cat是Linux命令行中的一个常用命令,用于显示文件的内容。以下是一些常见的使用cat的例子:
    1. 显示文件内容:
    cat [file-name]
    
    1. 合并多个文件并显示其内容:
    cat [file-1] [file-2] [file-3] ...
    

    wget

    wget是一个下载文件的工具,它用在命令行下,对于Linux和编程用户是必不可少的工具。

    语法格式

    wget [options] [url]
    

    例如,使用wget下载redis的tar.gz文件:

    wget https://download.redis.io/releases/redis-6.0.8.tar.gz
    

    该命令会下载文件到当前工作目录中,在下载过程中,会显示进度条、文件大小、下载速度等。

    接下来介绍几个常用的选项参数。

    使用 -O 选项以其他名称保存下载的文件

    要以其他名称保存下载的文件,使用-O选项,后跟指定名称即可:

    wget -O redis.tar.gz https://download.redis.io/releases/redis-6.0.8.tar.gz
    

    使用 -P 选项将文件下载到指定目录

    默认情况下,wget将下载的文件保存在当前工作目录中,使用-P选项可以将文件保存到指定目录下,例如,下面将将文件下载到/usr/software目录下:

    wget -P /usr/software https://download.redis.io/releases/redis-6.0.8.tar.gz
    

    使用 -b 选项在后台下载

    我们可以使用-b选项在后台下载文件:

    wget -b https://download.redis.io/releases/redis-6.0.8.tar.gz
    
    

    默认情况下,下载过程日志重定向到当前目录中的wget-log文件中,要查看下载状态,可以使用tail -f wget-log查看。

    另外,我上周遇到一个同事问我如何用wget下载网页,把html和css也下载了,这就需要递归下载了,详细参数如下:

    递归下载:
     -r,  --recursive          指定递归下载。
     -k,  --convert-links      让下载得到的 HTML 或 CSS 中的链接指向本地文件。
     -p,  --page-requisites    下载所有用于显示 HTML 页面的图片之类的元素。
    

    定时任务

    Linux 中的定时任务可以通过 crontab 命令来配置和管理。定时任务就是你想半夜让机器清理一下下载的文件啥的,在后端是很常见的命令。( 这个不用记,用的时候稍微查下资料,知道有这么一个功能就行)

    首先介绍一下 cron进程,也就是定时任务的进程。

    1.cron进程是linux中的守护进程,在系统后台运行

    2.linux的crontab服务默认每隔一分钟去读取一次/var/spool/cron,/etc/crontab,/etc/cron.d下面所有的内容

    3.编辑crontab文件后系统会自动存放在/var/spool/cron/目录中。

    crontab命令

    1.编辑/创建命令

    [root@localhost]# crontab -e

    当系统不存在crontab文件时,输入此命令即为创建,已存在文件即为编辑。

    2.查看当前所有定时任务

    [root@localhost]# crontab -l

    前5个数字分别对应:

    分钟小时日期月份星期
    0~590~231~311~120到7(0或7代表星期日)

    图解每行的格式如下:

    * * * * * command
    - - - - -
    | | | | |
    | | | | ----- Day of week (0 - 7) (Sunday = both 0 and 7)
    | | | ------- Month (1 - 12)
    | | --------- Day of month (1 - 31)
    | ----------- Hour (0 - 23)
    ------------- Minute (0 - 59)
    

    每一个字段可以填写特定的数字,也可以填写一个通配符 * 表示每一个时刻都执行该命令。

    例如:每天的 12:30 执行 command

    30 12 * * * command
    

    curl

    cURL是一个命令行工具,用于从服务器传输数据。它支持多种协议,如HTTP、HTTPS、FTP等。

    以下是使用cURL发送GET请求以检索网站HTML内容的示例:

    curl https://www.example.com
    

    使用以下命令可以使用POST请求发送数据到服务器:

    curl -d "name=value" https://www.example.com/submit
    

    您还可以在请求中包括头信息:

    curl -H "Content-Type: application/json" -X POST -d '{"key":"value"}' https://www.example.com/api
    

    第一部分linux命令完结

    这些基础命令就差不多了,有人说shell脚本要掌握,我告诉你完全没必要了,了解一下node的zx库,直接使用node语法写脚本吧,详细内容请看: Admin.net/post/697998…

    docker

    为啥先讲docker呢,是因为我们可以用docker自己搭建一个linux环境,然后在里面练习linux命令,所以我们还可以下载node镜像,nginx镜像,redis镜像来练习响应的命令。

    为什么需要docker

    对于前端而言,docker的意义在于

    • 不用繁杂的环境配置,比如mysql,你需要下载mysql镜像,就可以使用了
    • 部署简单,并且多环境下部署行为一致,毕竟都是程序猿嘛,别太在意前端后端的划分,毕竟我们前端弄个服务自己玩也很常见,而且简单的后端crud太简单了,比学html都简单

    安装docker

    这个不讲了,网上一大堆。主要是不同的系统安装方式不一样。

    docker镜像原理

    docker底层原理很复杂,对于我们使用镜像来说,最最重要的就是理解镜像的基本原理

    【前端运维】打通任督二脉!(linux + docker)

    • Docker镜像是由特殊的文件系统叠加而成
      • 如上图
    • 最底端是bootfs,也就是操作系统内核,比如linux内核
    • 第二层是rootfs,比如我们的linux发行版,有centos,ubuntu等等
    • 再往上可以叠加其他镜像文件
    • 接下来最重要的就是联合文件系统,我们不用细究原理,就明显它是一个分层的架构即可。

    采用这种分层结构最大的一个好处就是共享资源,比如有多个镜像都从相同的base镜像构建而来,那么宿主机只需要在磁盘上保存一份base镜像,同时内存中也只需要加载一份base镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

    举个例子:

    请问:

    1、Docker中一个centos镜像为什么只有200MB,而一个centos操作系统iso文件要几个G? 答:Centos的iso镜像文件包含了bootfs和rootfs,而docker的centos镜像复用操作系统的bootfs,只有rootfs和其他镜像层

    2、Docker中的一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70MB? 答:由于docker中镜像是分层的,tomcat虽然只有70多MB,但它需要依赖于父镜像和基础镜像,还要把bootfs和rootfs也打包到一起,对外暴露名字叫tomcat镜像而已,实际还有很多其他父镜像呢

    docker服务相关命令

    主要就是操作daemon的命令

    我们在命令行使用的是docker的客户端,然后把命令传递给了docker的守护进程daemon,它是管理所有镜像和镜像实例的主人。

    可以分为

    • 启动docker服务
    systemctl start docker
    
    • 停止docker 服务
    systemctl stop docker
    
    • 重启docker服务
    systemctl restart docker
    
    • 查看docker 服务状态
    systemctl status docker
    
    • 设置开机启动docker
    systemctl enable docker
    

    docker 镜像相关命令

    • 查看镜像: 查看本地所有镜像
    docker images
    docker images -q # 查看所用镜像id
    
    • 搜索镜像:从网络中查找需要的镜像
    docker search 镜像名称
    
    • 拉取镜像:从docker仓库下载镜像到本地,镜像名称格式为:名称:版本号,如果版本号不指定则是最新的版本,如果不知道镜像版本,可以去docker hub 搜索对应镜像查看
    docker pull 镜像名称
    
    • 删除镜像:删除本地镜像

    下面的rmi意思是rm images的意思。

    docker rmi 镜像id # 删除指定本地镜像
    docker rmi `docker images -q` # 删除所有本地镜像
    

    docker 容器相关命令

    • 查看容器
    docker ps # 查看正在运行的容器
    docker ps -a # 查看所有容器
    docker ps -a -q # 查看所有容器的id号
    
    • 创建并启动容器
    docker run 参数
    

    参数说明:

    1. -i:保持容器运行、通常与-t同时使用。加入it这两个参数以后,容器创建后自动进入容器中,退出容器后,容器自动关闭。
    2. -t:为容器重新分配一个伪输入终端
    3. -d:以守护模式运行容器。创建一个容器在后台运行,需要使用docker exec进人容器。退出后,容器不会关闭。
    4. --name,创建容器的名字

    这里只需要记住两个最基础的用法:

    docker run -it --name=xx centos:tag /bin/bash
    

    意思是docker 启动了一个centos镜像,版本是冒号后面的 tag,比如7版本,这个tag就是7,比如8版本,这个tag就是8。

    后面的/bin/bash的作用是表示载入容器后运行bash ,docker中必须要保持一个进程的运行,要不然整个容器启动后就会马上kill itself,这个/bin/bash就表示启动容器后启动bash。

    此时进入之后,要退出可以输入exit。但是你退出容器后,整个容器就消失了,我们如何让这个容器保持运行状态呢?

    docker run -id --name=xx centos:tag /bin/bash
    

    非常重要的点:docker run会增加一层文件系统,所以你的docker run 不要随意写,体积会更大,但是另一方面你要学会利用docker run创建缓存,比如node_modules的缓存,只要package.json不变化,node_modules里的东西就不要重新下载了。

    • 进入容器
    docker exec 参数 # 退出容器,容器不会关闭
    
    • 停止容器
    docker stop 容器名称
    
    • 启动容器
    docker start 容器名称
    
    • 删除容器:如果容器是运行状态则会删除失败。需要停止容器才能删除
    docker rm 容器名称
    

    查看日志 docker里的日志

    docker logs  + container的id或者name
    
    • -f : 跟踪日志输出
    • --tail :仅列出最新N条容器日志

    跟踪日志

     docker run -d --name topdemo centos /usr/bin/top -b
     docker attach topdemo
    

    这里注意,随着时间的推移,docker日志会越来越大,所以我们需要在启动docker的时候限制一下日志大小。

    配置数据卷

    这个挺重要的,当docker镜像关闭,那么docker中存储的数据其实也没了,为了让数据持久化,比如mysql的docker镜像能保存数据,就需要配置数据卷。

    配置的数据卷其实就是宿主机的一个目录而已

    【前端运维】打通任督二脉!(linux + docker)

    而且数据是同步的,你在宿主机上增删改查该目录下的文件,容器会同步,反之也是。

    • 创建启动容器时,使用-v 参数设置数据卷
    docker run ... -v 宿主机目录(文件):容器内目录文件
    
    • 注意事项

      • 目录必须是绝对路径
      • 如果目录不存在,会自动创建
      • 可以挂载多个数据卷

    dockerfile

    自动化ci/cd你肯定是要写dockerfile脚本的,所以很重要。

    Dockerfile是Docker容器镜像的构建脚本,用来指定创建镜像所需的步骤。每一条命令将会在当前镜像的基础上构建一个新镜像层。Dockerfile中通常包含如下内容:

    • 基础镜像的指定(FROM)

      • 指定dockerfile是根据哪个镜像构建的
    • 文件的复制(COPY)和移动(ADD)

      • COPY是复制文件,build的时候复制文件到image中,比如前端常常要复制package.json文件
      • ADD是添加文件,build的时候添加文件到image中 不仅仅局限于当前build上下文 还可以来源于远程服务
    • 环境变量的设置(ENV)

      • 指定build时候的环境变量
    • 工作目录的设置(WORKDIR)

      • 指定容器内部的工作目录,如果没有创建则自动创建,如果指定/使用的是绝对地址,如果不是/开头那么是在上一条workdir路径的基础上的相对路径
    • 容器启动时需要运行的命令(CMD)

      • 用于指定容器启动时运行的命令
      • 例如: CMD ["executable","param1","param2"]:表示在容器内执行的命令。
    • EXPOSE 暴露端口

      • 注意,这个暴露端口的命令并不是真的docker做了啥,因为真正端口映射是在 -p命令上,只是告诉你这个docker服务有暴露端口而已
    • RUN 执行命令

      • 执行一段命令,一般就是linux命令,默认是 /bin/sh. -RUN在下一次构建期间,指令缓存不会自动失效。可以使用--no-cache标志使指令缓存无效
    • Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大,可以使用 && 符号连接命令,这样执行后,只会创建 1 层镜像

    例如

    RUN /bin/bash -c 'source $HOME/.bashrc; \
    echo $HOME'
    

    Dockerfile通过“docker build”命令读入,并按照指定的步骤生成镜像。通过生成的镜像可以创建、启动Docker容器。

    docker build

    "docker build"命令是用于构建Docker镜像的命令。该命令需要一个Dockerfile文件作为输入,并从中生成一个Docker镜像。

    "docker build"命令的语法如下:

    docker build [OPTIONS] PATH | URL | -
    

    其中:

    • PATH:指向Dockerfile文件的路径;
    • URL:指向Git repository或者其他远程文件存储的地址;
    • -:表示从标准输入读入Dockerfile。

    其中 -t-f是常使用的参数,-t为指定构建镜像的名字和版本,格式为'name:tag'-f为指定其他目录下的DockerFIle文件.

    实例:

    假设在当前目录下存在一个名为Dockerfile的文件,执行以下命令可以生成名为"myimage",标签为"v1.0"的镜像:

    docker build -t myimage:v1.0 .
    

    技巧

    我们在docker run -it 的时候,就算退出容器,创建的容器实例还会存在,只不过是stop状态,如果我们想退出的时候这个实例直接就删掉,该如何做呢:

    docker run --rm -it xx
    

    docker网络

    这块非常重要,要不,你根本理解不了为啥容器ping容器可ping通,为啥宿主机ping容器也可以ping通,不设置 -p也就是端口映射,外网,也就是用户的浏览器访问不到你的docker容器。

    有些基础的网络知识需要具备,我这里就不赘述了。比如:

    • ip是什么,有什么用
    • 子网掩码是什么,有什么用
    • 网关、DNS、端口号是什么,有什么用

    还有网络常用的linux命令

    ifconfig
    

    【前端运维】打通任督二脉!(linux + docker)

    docker0,是docker0相当于交换机的作用,可以帮助docker实例传递网络信息。

    eth0,本地网卡

    lo:本地环回地址(127.0.0.1)

    bridge网络

    我们前端基本用个bridge网络就行了,这是docker默认的。

    【前端运维】打通任督二脉!(linux + docker)

    首先你看Container Test1有自己的网络地址和虚拟网卡eth0,请问它可以访问外网吗?

    答案是可以的,为啥呢,docker里的容器会通过NAT转换,把自己的ip地址映射成宿主机的eth0的对外的ip地址。

    反过来呢?外部的机器,比如你的电脑能访问这个服务的docker服务吗,明显是不能的,因为我们最多访问到宿主机的eth0。(所以需要 -p参数让docker容器暴露端口给宿主机)

    最后介绍一下桥接网络对于docker和宿主机能够互相ping通的意义!

    桥接在虚拟环境中特别有用,因为它允许虚拟机与主机或其他虚拟机之间的通信。桥接技术可以实现不同网段之间的网络互通。

    也就是说,桥接模式,让宿主机跟docker在同一个网段了,所以可以互相ping通。

    更详细内容,请看www.cnblogs.com/ZhuChangwu/…

    docker compose

    docker compose为啥要用呢,主要是我们起一个nodejs容器,可能同时还要起nginx和mysql的容器,如何同时启动和管理这3个容器呢,docker compose就是一个方案,使用步骤如下:

    1、利用Dockerfile定义运行环境镜像

    2、使用docker-compose.yml定义组成应用的各个服务

    3、运行docker-compose up 启动应用

    这里举一个例子,是我当时自己写的部署nestjs的项目的yml文件,当时是先写了一个搭建node环境的dockerfile

    # 引用镜像
    FROM node:16-alpine
    
    # MAINTAINER mengxiang
    
    # workdir指令设置Dockerfile中的任何RUN、CMD、COPY、ADD、ENTRPOINT的工作目录
    WORKDIR /usr/src/app/
    
    # COPY 是分层的,package.json 提前,只要没修改,就不会重新安装包
    COPY package*.json ./
    
    RUN yarn config set registry https://registry.yarnpkg.com/ && yarn install
    
    # 安装完毕后复制当前目录所有文件到镜像目录里面
    COPY ./ ./
    
    EXPOSE 3000
    
    CMD ["npm", "run", "start"]
    

    docker-compose.yml

    version: '3' # 3版本
    
    services:
      santak_mysql: # 定义mysql服务
        image: mysql:5.7 # 直接使用镜像构建
        container_name: santak_mysql # 指定容器名称。
        environment:
          - MYSQL_ROOT_PASSWORD=123456 # 测试先用root用户跑起来
          - TZ=Asia/Shanghai # 指定时区
          - MYSQL_DATABASE=monitor # 创建初始数据库
        volumes:
          - ./mysql/data:/var/lib/mysql # 为了数据持久化
        command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci # 覆盖容器启动后默认执行的命令
        ports:
          - 3307:3306
        restart: always # 指定容器退出后的重启策略为始终重启。该命令对保持服务始终运行十分有效,在生产环境中推荐配置为 `always` 或者 `unless-stopped`
      server:
        build: #指定 `Dockerfile` 所在文件夹的路径(可以是绝对路径,或者相对 docker-compose.yml 文件的路径)。 `Compose` 将会利用它自动构建这个镜像,然后使用这个镜
          context: .
          dockerfile: Dockerfile
        ports:
          - 3000:3000
        environment:
          - TZ=Asia/Shanghai # 指定时区
        restart: always # 总是重启
        image: server # 镜像名称
        container_name: server # 容器名称
        depends_on: # 启动顺序
          - santak_mysql
    
    

    想了解所有dockerfile的字段,请看yeasy.gitbook.io/docker_prac…

    最后,我有一个docker讲解神级教程,有兴趣的同学可以私信我,都是免费的,纯分享,一起进步呗!go,go,go!

    参考资料

    《大型网站架构》--- 李智慧