簡體   English   中英

使用PyYAML編輯docker-compose.yml

[英]Editing docker-compose.yml with PyYAML

我有一個非常標准的docker-compose.yml,我需要以編程方式編輯數據庫的密碼。

由於它是YAML文件,因此我認為編輯和轉儲內容會很簡單。 到目前為止,我嘗試了PyYAML,它只是弄亂了docker-compose文件,我不知道為什么。

加載和轉儲相同的內容會破壞結構。

docker-compose.yml的內容:

version: '2'
services:
  web:
    container_name: xxx
    ports:
     - "80:80"
    volumes:
      - .:/xxx
    depends_on:
      - mysql
    build: .
  mysql:
    ports:
     - "32768:32768"
     - "3306:3306"
    container_name: xxx-mysql
    restart: always
    image: mariadb:latest
    environment:
      MYSQL_ROOT_PASSWORD: 'thiswillbechangeonsetupscript'
      MYSQL_DATABASE: 'xxxdb'
    volumes:
     - ./database:/var/lib/mysql
    ports:
      - "3306:3306"

這就是我加載和轉儲內容的方式:

import yaml

with open("docker-compose.yml", 'r') as ymlfile:
    docker_config = yaml.load(ymlfile)

with open("docker-compose.yml", 'w') as newconf:
    yaml.dump(docker_config, newconf)

這就是文件的保存方式。

services:
  mysql:
    container_name: xxx-mysql
    environment: {MYSQL_DATABASE: xxxdb, MYSQL_ROOT_PASSWORD: thiswillbechangeonsetupscript}
    image: mariadb:latest
    ports: ['3306:3306']
    restart: always
    volumes: ['./database:/var/lib/mysql']
  web:
    build: .
    container_name: xxx
    depends_on: [mysql]
    ports: ['80:80']
    volumes: ['.:/xxx']
version: '2'

有什么更好的方法嗎? 我想念的是什么?

PyYAML的默認轉儲是對葉節點使用流樣式(對於序列,使用[....] ,對於映射使用{...} ),因此,您應該做的最少是指定yaml.dump(....., default_flow_style=False)

然后,YAML規范指出不能保證鍵的順序,而您看到的是PyYAML以排序順序轉儲它們。

我可以建議使用ruamel.yaml (免責聲明:我是該程序包的作者),該程序的特定目標是允許這種往返操作與輸入相比具有最小的變化,而根本沒有變化。 包括鍵順序,流vs塊樣式,字符串引號等。

使用ruamel.yaml另一個原因是:如果在輸入中運行此程序:

import sys
import ruamel.yaml

yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.indent(sequence=3, offset=1)

with open("docker-compose.yml", 'r') as ymlfile:
    data = yaml.load(ymlfile)
yaml.dump(data, sys.stdout)

您將得到一個DuplicateKeyError

ruamel.yaml.constructor.DuplicateKeyError: while constructing a mapping
  in "docker-compose.yml", line 13, column 5
found duplicate key "ports" with value "[]" (original value: "[]")
  in "docker-compose.yml", line 24, column 5

因為ports在映射中作為鍵的值兩次出現,這是鍵mysql的值。 根據YAML規范(PyYAML失效的舊版本1.1和更新的1.2),這是不允許的,但是PyYAML靜默處置了第一個鍵值對,從而使端口32768保持未映射狀態。

從輸入中刪除最后兩行后,程序的輸出為:

version: '2'
services:
  web:
    container_name: xxx
    ports:
     - "80:80"
    volumes:
     - .:/xxx
    depends_on:
     - mysql
    build: .
  mysql:
    ports:
     - "32768:32768"
     - "3306:3306"
    container_name: xxx-mysql
    restart: always
    image: mariadb:latest
    environment:
      MYSQL_ROOT_PASSWORD: 'thiswillbechangeonsetupscript'
      MYSQL_DATABASE: 'xxxdb'
    volumes:
     - ./database:/var/lib/mysql

希望它足夠接近您的預期目的。

請注意,PyYAML去掉引號- "80:80" ,這是很好的,因為80:80不能被錯誤地解釋為60進制,但如果你用25端口變化的東西- 80:80- 25:25也是千差萬別使用像PyYAML這樣的YAML 1.1解析器時(與docker-compose一樣)與- "25:25" (the former equalling -1525`)不同

基於此,我制作了一個實用程序ruamel.dcw ,使用該功能來預處理ruamel.dcw compose文件,允許使用環境變量的默認值(如果未設置)和其他一些技巧,寫出一個臨時文件,然后調用docker-compose -f tmpfile ,您應該使用類似的技術,在運行后處理您的臨時文件。

編寫yaml時,需要添加default_flow_style=False

import yaml

with open("docker-compose.yml", 'r') as ymlfile:
    docker_config = yaml.load(ymlfile)

with open("docker-compose_new.yml", 'w') as newconf:
    yaml.dump(docker_config, newconf, default_flow_style=False)

然后,您將獲得以下輸出作為輸出,除了使用字母順序寫行外,該輸出與您的輸入類似:

services:
  mysql:
    container_name: xxx-mysql
    environment:
      MYSQL_DATABASE: xxxdb
      MYSQL_ROOT_PASSWORD: thiswillbechangeonsetupscript
    image: mariadb:latest
    ports:
    - 3306:3306
    restart: always
    volumes:
    - ./database:/var/lib/mysql
  web:
    build: .
    container_name: xxx
    depends_on:
    - mysql
    ports:
    - 80:80
    volumes:
    - .:/xxx
version: '2'

請注意,在原始docker-compose.yaml您兩次聲明了ports變量,因此yaml解析器將僅考慮最后一個變量。 要解決此問題,請刪除以下幾行:

ports:
  - "3306:3306"

然后,按上述說明運行寫入操作將得出以下結果:

services:
  mysql:
    container_name: xxx-mysql
    environment:
      MYSQL_DATABASE: xxxdb
      MYSQL_ROOT_PASSWORD: thiswillbechangeonsetupscript
    image: mariadb:latest
    ports:
    - 32768:32768
    - 3306:3306
    restart: always
    volumes:
    - ./database:/var/lib/mysql
  web:
    build: .
    container_name: xxx
    depends_on:
    - mysql
    ports:
    - 80:80
    volumes:
    - .:/xxx
version: '2'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM