分类 linux 下的文章

先是指定版本

version: '3'
现在已被废除,不需要写了

然后指定 service
每个service 都指定build字段或者image字段看是从dockerfile上构建镜像还是从拉取镜像
服务的名称直接缩进一格就好
container_name指定容器名称
ports指定开放的端口
depends_on指定该服务需要在哪些服务启动之后启动
environment指定环境变量
volumes指定数据卷

就是数据和容器内数据的映射
比如将容器内的某个文件夹保存在宿主机内的某个地方
也可以用docker的数据卷做持久化,在最外层需要多一个volumes字段,缩进一格放数据卷名称

在配置mysql的时候可以将sql文件映射到容器内/docker-entrypoint-initdb.d目录
映射好之后,容器启动会自动运行目录里面的sql文件。需要注意的是只有在首次创建数据库的时候会执行。所有如果对mysql做了持久化,就是将容器内/var/lib/mysql的东西映射到了本地或者数据卷,后面再次启动就不会执行,除非将持久化的内容删了,然后重新创建
mysql环境变量

  1. 环境变量优先级:

environment:

MYSQL_ROOT_PASSWORD: root123      # root密码(必需)
MYSQL_DATABASE:         # 创建的数据库名
MYSQL_USER:      # 创建的用户名
MYSQL_PASSWORD: # 用户密码

容器间通信需要使用networks来指定一个网络,和volume一样最后在配置url的时候将localhost或者127.0.0.1变成对应的服务名。
但是好像不用network指定网络也行。不过就是确实需要对应为服务名就是了。

更正:
可能是windows上的docker比较新,可以不指定network就默认为一个network,但是我部署到linux上的时候,ubuntu上装的一个docker compose就不支持,加上networks字段之后才正常工作

如果就是容器内自己用的话像是mysql,redis这种的端口应该就不用暴露出去,因为暴露出去是给宿主机用的。如果只是容器之间用的话就不暴露也行。

可以使用环境变量的方式配置application.propertiess里面的配置。将字段改为全大写,点变为短下划线即可。

最后使用

docker compose up -d

来后台启动

如果想要重新构建镜像可以使用

docker compose build
后面可以跟上对应的服务名表示单独构建某一个镜像

使用

docker compose down

来停止和删除容器

等于 stop + rm

示例:

services:
  qiannian:
    build: ./qiannian
    ports:
      - "8080:8080"
    depends_on:
      - mysql
      - redisL
    networks:
      - qiannian_network
  
  ocr:
    build: ./ocr
    networks:
      - qiannian_network

  aiservice:
    build: ./ai_service
    networks:
      - qiannian_network

  mysql:
    image: mysql:8.0
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: qiannian
    networks:
      - qiannian_network
    volumes:
      - qiannian_mysql:/var/lib/mysql
      - ./qiannian/script.sql:/docker-entrypoint-initdb.d/script.sql

  redisL:
    image: redis:6.2-alpine
    container_name: redis
    networks:
      - qiannian_network

volumes:
  qiannian_mysql:

networks:
  qiannian_network:
    driver: bridge

选用的基础镜像
python:3.11
python:3.11-slim
python:3.11-alpine

alpine对PaddlePaddle不兼容

复制文件到 /app 文件夹下面

docker里面每一行命令都是基于前一个命令执行之后的容器文件新开一个容器

使用WORKDIR可以将后面的容器目录cd到该目录后面

opencv系统依赖

# 安装OpenCV依赖的系统库
RUN apt-get update && apt-get install -y \
    libgl1  \
    libglib2.0-0 \
    libsm6 \
    libxext6 \
    libgomp1 \
    libjpeg-dev \
    libpng-dev \
    libtiff-dev \
    libwebp-dev \
    && rm -rf /var/lib/apt/lists/*

关键依赖解释:

  • libgl1 - OpenGL支持(GUI功能)
  • libglib2.0-0 - GLib库
  • libsm6, libxext6, libxrender-dev - X11图形库
  • libgomp1 - OpenMP并行计算
  • libgtk-3-dev - GTK库(GUI界面)
  • libavcodec-dev, libavformat-dev, libswscale-dev - 视频编解码库
  • libjpeg-dev, libpng-dev, libtiff-dev, libwebp-dev - 图像格式支持

最小化安装(如果不需要GUI功能):

RUN apt-get update && apt-get install -y \
    libgl1 \
    libglib2.0-0 \
    libsm6 \
    libxext6 \
    libgomp1 \
    && rm -rf /var/lib/apt/lists/*

可以先创建虚拟环境,然后用
然后安装一下需要的包,最好使用

pip freeze > requirements.txt

保存下依赖

之后在dockerfile里面可以在copy完之后将依赖下载一下
最后可以使用CMD命令作为启动容器的默认命令,来起一个程序

使用

docker build -t name:tag .

来构建镜像
使用

docker images

来查看镜像
使用

docker run -d -p port:port --name name image:tag

来启动镜像

常用参数:

  • -d:后台运行
  • -p 8000:8000:端口映射(主机端口:容器端口)
  • --name my-container:给容器命名
  • -v /host/path:/container/path:挂载目录
  • -e ENV_VAR=value:设置环境变量

示例:

FROM python:3.11-slim

COPY . /app

WORKDIR /app

# 安装opencv依赖系统库
RUN apt-get update && apt-get install -y \
    libgl1 \
    libglib2.0-0 \
    libsm6 \
    libxext6 \
    libgomp1 \
    libjpeg-dev \
    libpng-dev \
    libtiff-dev \
    libwebp-dev \
    && rm -rf /var/lib/apt/lists/*

RUN pip install -r requirements.txt

EXPOSE 18689

CMD ["python", "ocr_service.py"]
FROM python:3.11-slim

COPY . /app

WORKDIR /app

RUN pip install -r requirements.txt

EXPOSE 7373

CMD ["python", "main.py"]

先是看下pom.xml里面的java版本,然后选择基础镜像

# 官方OpenJDK镜像(推荐)
FROM openjdk:17-jdk-slim
FROM openjdk:11-jdk-slim
FROM openjdk:8-jdk-slim

# Eclipse Temurin(更好的性能)
FROM eclipse-temurin:17-jdk
FROM eclipse-temurin:11-jdk

可以使用多阶段构建
如果源路径为文件夹,复制的时候不是直接复制该文件夹,而是将文件夹中的内容复制到目标路径。

使用

FROM maven:3.8.5-openjdk-17 AS builder

作为构建jar包时的镜像
https://hub.docker.com/_/maven/tags
这里可以搜索一下tag,主要就是看下jdk版本。

后面使用

FROM openjdk:17-jdk-slim

作为运行环境
两个镜像分隔,可以使最后的的最终镜像大小变小

可以使用

COPY --from=builder

复制前一阶段的文件

如果使用springboot插件需要删除<skip>true</skip>
这个会使SpringBoot插件跳过打包过程
导致没有main-class,运行jar包时报错

no main manifest attribute, in /app/xxx.jar

示例:

FROM maven:3.8.5-openjdk-17 AS builder

COPY . ./app

WORKDIR /app

RUN mvn clean package -DskipTests

FROM openjdk:17-jdk-slim

COPY --from=builder /app/target/xxx-0.0.1-SNAPSHOT.jar /app/xxx.jar

EXPOSE 8080

CMD ["java", "-jar", "/app/xxx.jar"]

后端有点问题一直拖到现在,学长在摸鱼,我也闲着无聊先去看下。

主要是python脚本没有跑起来。

  1. 看下原来的代码在哪个地方用到python

我发现之前上传的是我有改过的,可能是因为我有部分的地方改过所以导致了用不了

服务器上面是没有安装python3.11的,所以得装一个python3.11

问了一下gpt,直接就是下了源码然后编译,目前来看还算是比较顺利

离线安装的依赖版本和本地的python版本一致

因为我电脑上的是3.12,服务器上需要的是3.11

所以之前本地打包的依赖服务器的安装不了

现在得先在本地启一个3.11的虚拟环境然后在虚拟环境下再来下载这些依赖

先是用scoop安装一下python311

scoop bucket add versions
scoop install versions/python311

然后创建一个虚拟环境

python311 -m venv py311env

然后激活虚拟环境(我用的是git bash)

source py311env/Scripts/activate

之后再下载依赖

mkdir my_pkgs
cd my_pkgs

pip download pandas scikit-learn keras numpy openpyxl matplotlib mysql-connector-python

然后打包成tar,在服务器上解压,再用pip安装

pip3 install --no-index --find-links=. pandas scikit-learn keras numpy openpyxl matplotlib mysql-connector-python

有点尴尬,忘记了电脑是windows,下的依赖只能是windows用不能给linux用

现在是打算用wsl重复一下上面的步骤

wsl上面需要还是手动编译一个python3.11

先要安装一下编译的依赖:

sudo su # 获取权限
sudo apt-get update
# 随文章进行而更新,依赖应该是全的
sudo apt-get install -y build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev libsqlite3-dev wget

然后就是编译安装

cd /opt
wget https://www.python.org/ftp/python/3.11.9/Python-3.11.9.tgz # 下载python
tar -xzf Python-3.11.9.tgz
cd Python-3.11.9

# 安装编译依赖(如果有权限,可以让管理员预装)
# CentOS: yum groupinstall "Development Tools"
# Debian/Ubuntu: apt-get install build-essential

# 编译并安装到自定义目录(不要覆盖系统 Python 2.7)
sudo ./configure --prefix=/opt/python3.11 --enable-optimizations
sudo make -j$(nproc)    # 编译时间较长
sudo make install

配置环境变量:

# 加入环境变量
echo 'export PATH=/opt/python3.11/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

# 验证版本
python3 --version

目前来说还算顺利

后面下载依赖的时候不知道为什么还是下的3.12的版本,可能pip直接安装是这样的?不懂,还是得建一个虚拟环境试下

创建虚拟环境失败,其实之前编译的时候有问题,但是我直接给忽略了,现在看来应该是编译出问题了,感觉wsl好像什么都没有。

问了一个gpt报错,说是因为少了依赖,先下完依赖之后再更新

还是得建一个虚拟环境,不过python的安装倒是顺利,不错。

目前好像是因为说内网的那个linux的版本比较老,一些包不支持,所以得专门下载低版本去安装希望顺利

可以先查看一下支持哪些平台

python3 -m pip debug --verbose

然后对于某一个包可以指定平台下载,例如:

pip download \
  --only-binary=:all: \
  --platform manylinux2014_x86_64 \
  --python-version 311 \
  --implementation cp \
  --abi cp311 \
  Pillow==10.0.1

目前都挺顺利的,但是到了要运行的时候发现内部少了Python 标准库模块 ctypes

应该是编译的问题,问了一下gpt说是服务器少了libffi 开发依赖
所以现在是先让那边的管理员看能不能解决,或者干脆帮忙装一下python3.11,唉。

至少可以先停一会儿了。

后面因为连不了网,他们那边也是没有解决方法,只能是我这里继续。

我查了一下linux版本是Centos7,然后网上找了一个rpm的包

https://ftp.iij.ad.jp/pub/linux/centos-vault/centos/7.7.1908/cr/x86_64/Packages/

https://ftp.iij.ad.jp/pub/linux/centos-vault/centos/7.7.1908/cr/x86_64/Packages/libffi-devel-3.0.13-19.el7.x86_64.rpm

本地安装了一下这个依赖,然后再重新编译,目前貌似没有什么问题,一切顺利

sudo yum install ./*.rpm

装好了之后,重新编译python3之后又运行了一遍脚本,然后补装了一个库,总归是可行了。

之后就是把服务重新启动一下,过一两天看下数据库的数据,如果没有问题的话,这个就解决了,可喜可贺,可喜可贺。

在 Linux 上安装了 etcd 后,可以通过以下几种方式查看它的状态:


方法一:使用 etcdctl 工具

etcdctl 是 etcd 的命令行工具,可以用于查看集群状态、成员信息等。

1. 查看 etcd 版本

etcdctl version

2. 设置环境变量(如果你是使用默认配置)

export ETCDCTL_API=3

3. 查看健康状态

etcdctl endpoint health

如果 etcd 正常运行,会返回类似:

127.0.0.1:2379 is healthy: successfully committed proposal: took = 1.233ms

4. 查看成员列表

etcdctl member list

5. 查看集群状态

etcdctl endpoint status --write-out=table

方法二:使用 systemd 查看服务状态

如果你是使用 systemd 安装/启动的 etcd,可以使用:

systemctl status etcd

也可以用:

journalctl -u etcd -f

实时查看日志输出。


方法三:查看进程和监听端口

查看是否有 etcd 进程运行:

ps aux | grep etcd

查看 etcd 是否监听了默认端口 2379:

ss -tunlp | grep 2379

方法四:通过 HTTP API(如果你开放了接口)

例如:

curl http://localhost:2379/health

返回:

{"health":"true"}

说明服务正常。