跳转至

环境学习

 

约 1795 个字 • 422 行代码 预计阅读时间 15 分钟


Linux shell

参考:Linux 命令行 | LINUX-TUTORIAL

先集中学习一下最基础的linux shell命令。至于运维、环境配置等进一步的操作,再议再议🤪

下面的九大分类已包含大部分日常所需:

  • 查看与帮助
  • 文件目录管理
  • 文件内容查看
  • 文件压缩解压
  • 用户管理
  • 系统管理
  • 网络管理
  • 硬件管理
  • 软件管理

查看与帮助

本节涉及命令

help/whatis/info/which/whereis/man(不是牢大)

help

用于查看帮助信息

rmdir --help

whatis

查询一个命令执行什么功能,即feature查询

  ~ whatis git
Git (3pm)            - Perl interface to the Git version control system
git (1)              - the stupid content tracker
  ~ whatis -w "su*"
su (1)               - run a command with substitute user and group ID
subgid (5)           - the configuration for subordinate group ids
subpage_prot (2)     - define a subpage protection for an address range
subuid (5)           - the configuration for subordinate user ids
sudo (8)             - execute a command as another user
sudo.conf (5)        - configuration for sudo front-end
sudo_logsrv.proto (5) - Sudo log server protocol
sudo_logsrvd (8)     - sudo event and I/O log server
sudo_logsrvd.conf (5) - configuration for sudo_logsrvd
sudo_plugin (5)      - Sudo Plugin API
sudo_root (8)        - How to run administrative commands
sudo_sendlog (8)     - send sudo I/O log to log server
sudoedit (8)         - execute a command as another user
sudoers (5)          - default sudo security policy plugin
sudoers_timestamp (5) - Sudoers Time Stamp Format
sudoreplay (8)       - replay sudo session logs
suffixes (7)         - list of file suffixes
sulogin (8)          - single-user login
sum (1)              - checksum and count the blocks in a file
suseconds_t (3type)  - integer time

info

命令的详细说明,是whatis的延伸

which

PATH查询

  ~ which zsh
/usr/bin/zsh

whereis

搜索程序名对应的所有文件,包括二进制程序、源代码文件和 man 手册页等相关文件的路径

对应Win下的where

  ~ whereis git
# 找到可执行文件和帮助文档
git: /usr/bin/git /usr/share/man/man1/git.1.gz

man

命令使用手册,即help

善用快捷键,如w/z翻页,>/<首尾跳转,q退出。具体可h查询

  ~ man git
# 打开文档后,可见名字、概要、描述、可选项、常见命令等提示

文件目录管理

本节涉及命令

cd/ls/pwd/mkdir/rmdir/tree/touch/ln/rename/stat/chmod/chown/find/cp/scp/mv/rm

linux目录树与功能

当我们列出一个目录的详细信息时,可以得到

  ~ ls -l
# 目录下文件共占用80KB
total 80
drwxr-xr-x  2 root root  4096 Feb 16  2025 Linear-Algebra-Left-Undone
drwxr-xr-x  4 root root  4096 Feb 28  2025 go
-rw-r--r--  1 root root 64138 Oct  2 16:46 ion
drwxr-xr-x 13 root root  4096 Dec  8  2024 rocos
drwxr-xr-x  2 root root  4096 Dec  7  2024 scripts

对于每一列,以空格分开,分别代表着该文件的:

  • 属性
  • 硬链接数量(可视为子文件夹数量)
  • 文件所有者
  • 文件所属用户组
  • 文件大小
  • 最后修改时间(年月日)
  • 文件/目录名

对于属性的10个字母,以1+3*3的视角去看待,分别表示着文件类型与用户权限

第一个符号表示文件类型:

  • d → 目录
  • - → 文件
  • l → 链接文档(link file)
  • b → 装置文件里面的可供储存的接口设备(可随机存取装置)
  • c → 装置文件里面的串行端口设备,例如键盘、鼠标(一次性读取装置)

后面三组(每组的顺序都是rwx,分别代表可读/可写/可执行;若无权限则用-表示)分别说明文件的拥有者、拥有者同组用户、其他用户的权限

cd

目录跳转

cd          # 切换到用户主目录
cd ~        # 切换到用户主目录
cd -        # 切换到上一个工作目录
cd ..       # 切换到上级目录
cd ../..    # 切换到上两级目录

ls

显示目录信息

ls        # 列出当前目录可见文件
ls -l     # 列出当前目录可见文件详细信息
ls -la    # 列出所有文件(包括隐藏)的详细信息
ls -lh    # 列出详细信息并以可读大小显示文件大小
ls -lt    # 按时间列出文件和文件夹详细信息
ls -ltr   # 按修改时间列出文件和文件夹详细信息

pwd

打印当前目录

mkdir

新建文件夹

rmdir

删除空文件夹

tree

目录可视化,可选项非常丰富,是做目录树的好帮手

touch

新建文件

in

创建链接(硬链接/符号链接)

![](https://cdn.jsdelivr.net/gh/dixiLOG/blogStatic/authcode-d28b04c2c0.png){: .zoom}
# 将目录 /usr/mengqc/mub1 下的文件 m2.c 链接到目录 /usr/liu 下的文件 a2.c
cd /usr/mengqc
ln /mub1/m2.c /usr/liu/a2.c

# 在目录 /usr/liu 下建立一个符号链接文件 abc,使它指向目录 /usr/mengqc/mub1
# 执行该命令后,/usr/mengqc/mub1 代表的路径将存放在名为 /usr/liu/abc 的文件中
ln -s /usr/mengqc/mub1 /usr/liu/abc

rename

重命名,可用mv平替

# 将 main1.c 重命名为 main.c
rename main1.c main.c main1.c

rename "s/AA/aa/" *             # 把文件名中的 AA 替换成 aa
rename "s//.html//.php/" *      # 把 .html 后缀的改成 .php 后缀
rename "s/$//.txt/" *           # 把所有的文件名都以 txt 结尾
rename "s//.txt//" *            # 把所有以 .txt 结尾的文件名的.txt 删掉

stat

文件状态显示

➜  ~ stat rocos
  File: rocos
  Size: 4096            Blocks: 8          IO Block: 4096   directory
Device: 8,48    Inode: 21531       Links: 13
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2025-10-02 16:59:56.972664273 +0800
Modify: 2024-12-08 15:41:06.884941531 +0800
Change: 2024-12-08 15:41:06.884941531 +0800
 Birth: 2024-12-08 15:40:17.350917325 +0800

chmod

权限修改

  -rw-r--r--
# ↑╰┬╯╰┬╯╰┬╯
# ┆ ┆  ┆  ╰┈ 0 其他人
# ┆ ┆  ╰┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ g 属组
# ┆ ╰┈┈┈┈ u 属组
# ╰┈┈ 第一个字母 `d` 代表目录,`-` 代表普通文件

每一组的三个权限以二进制赋值。如7意味着rwx

chmod u+x,g+w file  # 为文件f01设置自己可以执行,组员可以写入的权限
chmod u=rwx,g=rw,o=r file
chmod 764 file

# 将/home/wwwroot/里的所有文件和文件夹设置为755权限
chmod -R  755 /home/wwwroot/*

chown

目录所有者修改

# 将目录/usr/meng及其下面的所有文件、子目录的文件主改成 liu
chown -R liu /usr/meng

find

区别于whereisfind用于查找文件,操作很多,help/man一下

find . -type f -name "*" | xargs grep "140.206.111.111"

# 列出当前目录及子目录下所有文件和文件夹
find .

# 在 /home 目录下查找以 .txt 结尾的文件名
find /home -name "*.txt"
# 同上,但忽略大小写
find /home -iname "*.txt"

# 当前目录及子目录下查找所有以 .txt 和 .pdf 结尾的文件
find . -name "*.txt" -o -name "*.pdf"

# 匹配文件路径或者文件
find /usr/ -path "*local*"

# 基于正则表达式匹配文件路径
find . -regex ".*\(\.txt\|\.pdf\)$"
# 同上,但忽略大小写
find . -iregex ".*\(\.txt\|\.pdf\)$"

# 找出 /home 下不是以 .txt 结尾的文件
find /home ! -name "*.txt"

cp

将一个或多个源文件或者目录复制到指定的目的文件或目录。目标目录必须存在。

# 将文件 file 复制到目录 /usr/men/tmp 下,并改名为 file1
cp file /usr/men/tmp/file1

# 将目录 /usr/men下的所有文件及其子目录复制到目录 /usr/zh 中
cp -r /usr/men /usr/zh

# 强行将 /usr/men下的所有文件复制到目录 /usr/zh 中,无论是否有文件重复
cp -rf /usr/men/* /usr/zh

# 将目录 /usr/men 中的以 m 打头的所有 .c 文件复制到目录 /usr/zh 中
cp -i /usr/men m*.c /usr/zh

scp

跨服务器进行远程拷贝文件的

# 拷贝文件到远程服务器的指定目录
scp <file> <user>@<ip>:<url>
scp test.txt root@192.168.0.1:/opt

# 拷贝目录到远程服务器的指定目录
scp -r <folder> <user>@<ip>:<url>
scp -r test root@192.168.0.1:/opt

免密传输

mv

移动、重命名和覆盖

mv file1.txt /home/office/                      # 移动单个文件
mv file2.txt file3.txt file4.txt /home/office/  # 移动多个文件
mv *.txt /home/office/                          # 移动所有 txt 文件
mv dir1/ /home/office/                          # 移动目录
mv /usr/men/* .                                 # 将指定目录中的所有文件移到当前目录中

mv file1.txt file2.txt          # 重命名文件
mv dir1/ dir2/                  # 重命名目录
mv -v *.txt /home/office        # 打印移动信息
mv -i file1.txt /home/office    # 提示是否覆盖文件

mv -uv *.txt /home/office       # 源文件比目标文件新时才执行更新
mv -vn *.txt /home/office       # 不要覆盖任何已存在的文件
mv -f *.txt /home/office        # 无条件覆盖已经存在的文件
mv -bv *.txt /home/office       # 复制时创建备份

rm

删除操作

rm test.txt               # 删除文件
rm -i test.txt test2.txt  # 交互式删除文件
rm -r *                   # 删除当前目录下的所有文件和目录
rm -r testdir             # 删除目录下的所有文件和目录
rm -rf testdir            # 强制删除目录下的所有文件和目录
rm -v testdir             # 显示当前删除操作的详情

文件内容查看

本节涉及命令

cat/head/tail/vim/grep

cat

打印内容到shell

head/tail

显示文档前/后几行内容

tail file           # 显示文件file的最后10行
tail -n +20 file    # 显示文件file的内容,从第20行至文件末尾
tail -c 10 file     # 显示文件file的最后10个字符

vim

等于vi,我用的比较习惯。可通过菜鸟教程快速上手

grep

非常强大的文件检索工具

# 在多级目录中对文本递归搜索(程序员搜代码的最爱):
grep "class" . -R -n

# 忽略匹配样式中的字符大小写
echo "hello world" | grep -i "HELLO"

# 匹配多个模式:
grep -e "class" -e "vitural" file

# 只在目录中所有的.php和.html文件中递归搜索字符"main()"
grep "main()" . -r --include *.{php,html}

# 在搜索结果中排除所有README文件
grep "main()" . -r --exclude "README"

# 在搜索结果中排除filelist文件列表里的文件
grep "main()" . -r --exclude-from filelist

文件压缩解压

tar

用这个enough

tar -cvf log.tar log2012.log            # 仅打包,不压缩
tar -zcvf log.tar.gz log2012.log        # 打包后,以 gzip 压缩
tar -jcvf log.tar.bz2 log2012.log       # 打包后,以 bzip2 压缩

tar -ztvf log.tar.gz                    # 查阅上述 tar 包内有哪些文件
tar -zxvf log.tar.gz                    # 将 tar 包解压缩
tar -zxvf log30.tar.gz log2013.log      # 只将 tar 内的部分文件解压出来
  • 第一个字母(z/j/J)→ 压缩方式
  • 第二个字母(c/x/t)→ 压缩/解压/查看
  • vf→固定搭配

用户管理

![](https://cdn.jsdelivr.net/gh/dixiLOG/blogStatic/authcode-a7a804e166.png){: .zoom}

目前不常用,暂时搁置


系统管理

本节涉及命令

uname/reboot/shutdown/date/ps/kill/jobs

cat /etc/os-release

查看发行版

  ~ cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.1 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble

查看内核可用uname -a命令

  ~ uname -a
Linux localhost 6.6.87.2-microsoft-standard-WSL2 
#1 SMP PREEMPT_DYNAMIC Thu Jun  5 18:30:46 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux

reboot

重启

shutdown

关机

date

显示时间

ps

报告当前系统的进程状态;可以搭配 kill 指令随时中断、删除不必要的程序

# 按内存资源的使用量对进程进行排序
ps aux | sort -rnk 4

# 按 CPU 资源的使用量对进程进行排序
ps aux | sort -nk 3

kill

杀死进程

# 先用 ps 查找进程,然后用 kill 杀掉
ps -ef | grep vim
root      3171     341  0 19:58 pts/0    00:00:00 grep vim

kill 3171

jobs

查看后台任务


网络管理

本节涉及命令

curl/wget/ip/hostname/nslookup/host/nc/ss

curl

一个利用 URL 规则在命令行下工作的单文件传输工具,支持上传和下载

# 下载文件
curl http://man.linuxde.net/text.iso

# 下载文件,并查看进度
curl http://man.linuxde.net/test.iso --progress
########################################## 100.0%

wget

很强大的命令行下载工具

# 使用 wget 下载单个文件
wget http://www.linuxde.net/testfile.zip
# 它以“爬虫”模式、无视 robots.txt 规则、只针对目标目录、并过滤掉无关文件的方式,精准而完整地克隆了服务器上意外暴露的 .git 仓库
wget -r -np -nH --cut-dirs=0 -e robots=off -R "index.html*" http://URL

ip

代替ifconfig

ip link show                     # 查看网络接口信息
ip link set eth0 upi             # 开启网卡
ip link set eth0 down            # 关闭网卡
ip link set eth0 promisc on      # 开启网卡的混合模式
ip link set eth0 promisc offi    # 关闭网卡的混个模式
ip link set eth0 txqueuelen 1200 # 设置网卡队列长度
ip link set eth0 mtu 1400        # 设置网卡最大传输单元
ip addr show     # 查看网卡IP信息
ip addr add 192.168.0.1/24 dev eth0 # 设置eth0网卡IP地址192.168.0.1
ip addr del 192.168.0.1/24 dev eth0 # 删除eth0网卡IP地址

ip route show # 查看系统路由
ip route add default via 192.168.1.254   # 设置系统默认路由
ip route list                 # 查看路由信息
ip route add 192.168.4.0/24  via  192.168.0.254 dev eth0 # 设置192.168.4.0网段的网关为192.168.0.254,数据走eth0接口
ip route add default via  192.168.0.254  dev eth0        # 设置默认网关为192.168.0.254
ip route del 192.168.4.0/24   # 删除192.168.4.0网段的网关
route del default          # 删除默认路由
ip route delete 192.168.1.0/24 dev eth0 # 删除路由

hostname

主机名

nslookup

DNS查询

# sudo apt install dnsutils
  ~ nslookup www.jsdig.com
Server:         10.255.255.254
Address:        10.255.255.254#53

Non-authoritative answer:
Name:   www.jsdig.com
Address: 154.199.231.41

host

分析域名查询工具

  ~ host www.jsdig.com
www.jsdig.com has address 154.199.231.41
  ~ host -a www.jsdig.com
Trying "www.jsdig.com"
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59788
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.jsdig.com.                 IN      ANY

;; ANSWER SECTION:
www.jsdig.com.          526     IN      A       154.199.231.41

Received 47 bytes from 10.255.255.254#53 in 12 ms

nc

netcat,常见于CTF—pwn,用于端口监听

ss

netstat的现代版

#列出所有udp端口
  ~ ss -au
State    Recv-Q    Send-Q        Local Address:Port         Peer Address:Port   Process
UNCONN   0         0                127.0.0.54:domain            0.0.0.0:*
UNCONN   0         0             127.0.0.53%lo:domain            0.0.0.0:*
UNCONN   0         0            10.255.255.254:domain            0.0.0.0:*
UNCONN   0         0                 127.0.0.1:323               0.0.0.0:*
UNCONN   0         0                     [::1]:323                  [::]:*
# 显示所有端口的统计信息
  ~ ss -s
Total: 189
TCP:   3 (estab 0, closed 0, orphaned 0, timewait 0)

Transport Total     IP        IPv6
RAW       0         0         0
UDP       5         4         1
TCP       3         3         0
INET      8         7         1
FRAG      0         0         0

硬件管理

本节涉及命令

df/du/top/free

df

用于显示磁盘分区上的可使用的磁盘空间(KB)

可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息

  ~ df -h
Filesystem      Size  Used Avail Use% Mounted on
none            3.9G     0  3.9G   0% /usr/lib/modules/6.6.87.2-microsoft-standard-WSL2
none            3.9G  4.0K  3.9G   1% /mnt/wsl
drivers         181G  161G   20G  90% /usr/lib/wsl/drivers
/dev/sdd       1007G  3.9G  952G   1% /
none            3.9G   88K  3.9G   1% /mnt/wslg
none            3.9G     0  3.9G   0% /usr/lib/wsl/lib
rootfs          3.9G  2.7M  3.9G   1% /init
none            3.9G  560K  3.9G   1% /run
...

题外话 | 查询目录下文件大小

  ~ du -sh * | sort -h

top

任务管理器

top - 20:27:06 up  3:39,  1 user,  load average: 0.00, 0.00, 0.00
Tasks:  25 total,   1 running,  23 sleeping,   1 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   7941.2 total,   7197.9 free,    702.7 used,    201.7 buff/cache
MiB Swap:  16384.0 total,  16384.0 free,      0.0 used.   7238.5 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
      1 root      20   0   21800  12384   9440 S   0.0   0.2   0:01.83 systemd
      2 root      20   0    3072   1792   1792 S   0.0   0.0   0:00.01 init-systemd(Ub
      8 root      20   0    3088   2008   1920 S   0.0   0.0   0:00.00 init
     59 root      19  -1   50440  15184  14288 S   0.0   0.2   0:02.07 systemd-journal
    108 root      20   0   25024   5888   4864 S   0.0   0.1   0:00.31 systemd-udevd
    193 systemd+  20   0   19600  12416  10240 S   0.0   0.2   0:00.29 systemd-resolve
    194 systemd+  20   0   91020   7552   6784 S   0.0   0.1   0:00.79 systemd-timesyn
    209 root      20   0    4236   2688   2432 S   0.0   0.0   0:00.09 cron
    210 message+  20   0    9592   4736   4352 S   0.0   0.1   0:00.59 dbus-daemon
    217 root      20   0   17956   8448   7552 S   0.0   0.1   0:00.32 systemd-logind
    219 root      20   0 1756096  13696  10624 S   0.0   0.2   0:00.98 wsl-pro-service
    221 root      20   0    3160   1920   1792 S   0.0   0.0   0:00.01 agetty
    225 syslog    20   0  222508   5504   4352 S   0.0   0.1   0:00.37 rsyslogd
    227 root      20   0    3116   1792   1664 S   0.0   0.0   0:00.01 agetty
    243 root      20   0  107008  22272  13184 S   0.0   0.3   0:00.10 unattended-upgr
    339 root      20   0    3080   1024    896 S   0.0   0.0   0:00.00 SessionLeader
    340 root      20   0    3096   1028    896 S   0.0   0.0   0:00.98 Relay(341)
    341 root      20   0   25164  21616   5760 S   0.0   0.3   0:14.60 zsh
    342 root      20   0    6668   4224   3584 S   0.0   0.1   0:00.01 login
    389 root      20   0   20328  11264   9216 S   0.0   0.1   0:00.37 systemd
    390 root      20   0   21156   3380   1664 S   0.0   0.0   0:00.00 (sd-pam)
    412 root      20   0    7828   5972   4096 S   0.0   0.1   0:00.16 zsh
    947 root      20   0   22200  12800   7552 T   0.0   0.2   0:00.04 vi
   1358 polkitd   20   0  308164   7680   6912 S   0.0   0.1   0:00.09 polkitd
   3990 root      20   0    9372   5632   3456 R   0.0   0.1   0:00.03 top

free

显示内存用量

  ~ free -h
               total        used        free      shared  buff/cache   available
Mem:           7.8Gi       706Mi       7.0Gi       3.5Mi       201Mi       7.1Gi
Swap:           16Gi          0B        16Gi

软件管理

apt-get

# 更新 apt-get
apt-get update

# 更新所有已安装的软件包
apt-get upgrade

# 将系统升级到新版本
apt-get dist-upgrade

# 安装一个软件包
apt-get install <packagename>

# 卸载一个已安装的软件包(保留配置文件)
apt-get remove <packagename>

# 卸载一个已安装的软件包(删除配置文件)
apt-get –purge remove <packagename>

# 如果需要空间的话,可以让这个命令来删除你已经删掉的软件
apt-get autoclean apt

# 把安装的软件的备份也删除,不过这样不会影响软件的使用的
apt-get clean

Docker

如果你想了解啥是Docker(它的底层架构与特点、与虚拟机的差异等),不妨看看Docker核心概念,或者直接点开其中的第一课

Docker和VMware的区别


绪论

Docker是目前最流行的Linux容器解决方案

它将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样

总体来说,Docker的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样

小试牛刀

这篇Docker快速入门用实例step by step演示了image拉取和容器制作与上传,属于是朗朗上手,我就不借花献佛了

备忘录

# 查看容器
docker ps -a
# 要删除所有已停止的容器
docker container prune -f
# 后台临时启动
docker run -d --rm -p 8080:80 ghcr.io/gchq/cyberchef:latest
# 容器停止
docker stop/kill <ID/NAME>

题外话

pushhub仓库后,本地的image便已经备份了,若存储捉急可删除

# 查询现有镜像
docker images
# 删除指定镜像
docker rmi <image_id  镜像名:tag>

docker compose

在实际的工程项目中往往涉及多个容器的协同,此时一个个run显得有些狼狈,于是Docker Compose应运而生

  • 容器编排工具
  • YAML文件(docker-compose.yml)定义一组服务,然后用一条命令就能启动 / 停止所有服务
  • 批量docker run+ 自动化配置

下面以Flask web + Redis为例走一遍compose全流程

环境:WIN11;WSL2下的powershell + docker-desktop

项目结构

compose-demo/
├─ docker-compose.yml
└─ app/
   ├─ Dockerfile
   ├─ requirements.txt
   └─ app.py

创建app

按照项目结构mkdirtouchCV一下内容

from flask import Flask
import os, redis

app = Flask(__name__)
r = redis.Redis(host=os.environ.get("REDIS_HOST","redis"), port=6379, db=0)

@app.route("/")
def index():
    r.incr("hits")
    return f"Hello from Flask! Hits: {r.get('hits').decode()}"

Flask 应用,每访问一次就对 Redis 的hits自增并返回

Flask>=2.0
redis>=4.0

写 Dockerfile

将app打包为镜像

FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

ENV FLASK_APP=app.py FLASK_ENV=development FLASK_RUN_HOST=0.0.0.0 FLASK_RUN_PORT=5000
CMD ["flask", "run"]

写 Docker-compose

version: "3.9"

services:
  web:
    build: ./app
    ports:
      - "5000:5000"
    volumes:
      - ./app:/app           # 开发时把本地代码挂进去实现热更新
    environment:
      - REDIS_HOST=redis
    depends_on:
      - redis
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5000/"]
      interval: 10s
      timeout: 5s
      retries: 3

  redis:
    image: redis:7-alpine
    volumes:
      - redis-data:/data

volumes:
  redis-data:
  • services 下定义两个服务:web(自建镜像)和 redis(直接拉官方镜像)
  • build: ./app:从 app 目录的 Dockerfile 构建镜像
  • ports:把容器 5000 端口映射到主机 5000
  • volumes:绑定挂载本地代码到容器(方便开发时修改立即生效)
  • depends_on:让web在启动时依赖redis(只是启动顺序,不保证服务就绪)
  • healthcheck:定义健康检查,Compose 会报告服务健康状况
  • volumes(最外层的):持久化 Redis 数据

可使用docker compose config检查文件是否报错

构建并启动

docker compose up
# 在后台启动,不占用终端
docker compose up -d

除了看见容器被启用外,访问 http://localhost:5000/ 能得到类似Hello from Flask! Hits: 21(刷新数加)的结果,说明运行成功

下面的命令可检查容器运行情况,与docker-desktop显示一致

# 查看状态
docker compose ps
# 查看日志(跟随)
docker compose logs -f

docker-desktop 截图

进入容器 bash

用于查看文件、运行命令、调试环境变量等

docker compose exec web sh

rebuild

更新代码(Dockerfile/依赖)后需要重建环境

docker compose up -d --build

停止与清理

docker compose down
docker compose down --volumes --rmi local
  • --volumes 会删除 docker-compose.yml 创建的命名卷,会丢数据
  • --rmi local 删除本地构建出来的镜像(非远程 pull 的镜像)