最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Python編排Dockerfile的代碼詳解

 更新時(shí)間:2024年08月11日 08:28:31   作者:netkiller-  
docker compose 是 docker 的容器編排工具,它是基于 YAML 配置,YAML 是一種配置文件格式,支持傳遞環(huán)境變量,但是對(duì)于復(fù)雜的容器編排顯得力不從心,于是我便開發(fā)這個(gè)程序,可以像寫程序一樣編排 docker,感興趣的的朋友可以參考下

使用 python 替代 docker compose 編排容器

docker compose 是 docker 的容器編排工具,它是基于 YAML 配置,YAML 是一種配置文件格式,支持傳遞環(huán)境變量,但是對(duì)于復(fù)雜的容器編排顯得力不從心。

于是我便開發(fā)這個(gè)程序,可以像寫程序一樣編排 docker ,可以充分發(fā)揮程序猿的想象力。

pip install netkiller-devops

編排 Dockerfile

from netkiller.docker import *
 
# 實(shí)例化 Dockerfile() 對(duì)象
nginx = Dockerfile()
 
# 基于什么鏡像
nginx.image('nginx:latest')
 
# 配置掛載卷
nginx.volume(['/etc/nginx','/var/log/nginx','/opt'])
 
# 運(yùn)行腳本
nginx.run('apt update -y && apt install -y procps')
 
# 暴漏端口
nginx.expose(['80','443'])
 
# 設(shè)置工作目錄
nginx.workdir('/opt')
 
# 打印 Dockerfile
nginx.show()		

運(yùn)行結(jié)果

FROM nginx:latest
VOLUME ["/etc/nginx","/var/log/nginx","/opt"]
RUN apt update -y && apt install -y procps
EXPOSE 80 443
WORKDIR /opt        

另一種寫法

from netkiller.docker import *
 
nginx = Dockerfile() 
nginx.image('nginx:latest').volume(['/etc/nginx','/var/log/nginx']).run('apt update -y && apt install -y procps').expose(['80','443']).workdir('/opt')
nginx.render()
nginx.save('/tmp/Dockerfile')

構(gòu)建 Docker 鏡像

from netkiller.docker import *
 
# 編排 Docker 鏡像
dockerfile = Dockerfile()
dockerfile.image('openjdk:8').volume(['/srv']).run(
    'apt update -y && apt install -y procps net-tools iputils-ping iproute2 telnet'
).expose(['80', '443']).workdir('/srv')
 
# 通過(guò) Service 設(shè)置鏡像名稱是 netkiller:openjdk8
image = Services('image')
image.build(dockerfile)
image.image('netkiller:openjdk8')
 
# 構(gòu)建鏡像
demo = Composes('demo')
demo.version('3.9')
demo.services(image)
demo.build()		

完整演示

#!/usr/bin/python3
#-*- coding: utf-8 -*-
##############################################
# Home	: http://netkiller.github.io
# Author: Neo <netkiller@msn.com>
# Upgrade: 2021-11-17
##############################################
try:
	import os,  sys
	module = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
	print(module)
	sys.path.insert(0,module)
	from netkiller.docker import *
except ImportError as err:
	print("%s" %(err))
 
dockerfile = Dockerfile() 
# dockerfile.label({'org.opencontainers.image.authors':'netkiller'})
dockerfile.image('openjdk:8-alpine')
# dockerfile.image('openjdk:8')
dockerfile.env({'ROCKETMQ_VERSION':'4.9.2','ROCKETMQ_HOME':'/srv/rocketmq', 'PATH':'${ROCKETMQ_HOME}/bin:$PATH'}) # 'JAVA_OPT':'"${JAVA_OPT} -server -Xms512m -Xmx2048m -Xmn128m"'
dockerfile.arg({'user':'rocketmq', 'group':'nogroup'})
dockerfile.run('wget https://dlcdn.apache.org/rocketmq/4.9.2/rocketmq-all-4.9.2-bin-release.zip && unzip rocketmq-all-4.9.2-bin-release.zip')
dockerfile.run('mv rocketmq-4.9.2 /srv/rocketmq-4.9.2 && rm -rf rocketmq-all-4.9.2-bin-release.zip')
dockerfile.run('ln -s /srv/rocketmq-${ROCKETMQ_VERSION} /srv/rocketmq')
dockerfile.run('adduser -S -D ${user}')
dockerfile.run(['chown ${user}:${group} -R /srv/rocketmq-${ROCKETMQ_VERSION}'])
dockerfile.expose(['9876'])
dockerfile.expose(['10909','10911','10912'])
dockerfile.copy('docker-entrypoint.sh','/srv/docker-entrypoint.sh')
dockerfile.run('chmod a+x /srv/docker-entrypoint.sh')
dockerfile.entrypoint('["/srv/docker-entrypoint.sh"]') 
dockerfile.workdir('${ROCKETMQ_HOME}')
# dockerfile.render()
# dockerfile.save('/tmp/Dockerfile')
 
rocketmq = Services('rocketmq')
rocketmq.build(dockerfile).image('registry.netkiller.cn/rocketmq/rocketmq:4.9.2').container_name('rocketmq')
# rocketmq.entrypoint('/srv/rocketmq/bin/mqnamesrv')
# rocketmq.ports('9876:9876').command('/srv/rocketmq/bin/mqnamesrv')
 
dockerfile = Dockerfile() 
dockerfile.image('registry.netkiller.cn/rocketmq/rocketmq:4.9.2')
dockerfile.run('ln -s /srv/rocketmq-${ROCKETMQ_VERSION} /srv/mqnamesrv')
dockerfile.cmd('/srv/mqnamesrv/bin/mqnamesrv')
dockerfile.workdir('/srv/mqnamesrv')
dockerfile.user('rocketmq:nogroup')
dockerfile.volume([
 	'/home/rocketmq/logs/rocketmqlogs'
])
 
mqnamesrv = Services('mqnamesrv')
mqnamesrv.build(dockerfile).image('registry.netkiller.cn/rocketmq/mqnamesrv:4.9.2').container_name('mqnamesrv').ports('9876:9876')
mqnamesrv.command('mqnamesrv')
 
dockerfile = Dockerfile() 
dockerfile.image('registry.netkiller.cn/rocketmq/rocketmq:4.9.2')
dockerfile.run('ln -s /srv/rocketmq-${ROCKETMQ_VERSION} /srv/mqbroker')
dockerfile.cmd('/srv/rocketmq/bin/mqbroker')
dockerfile.workdir('/srv/mqbroker')
dockerfile.user('rocketmq:nogroup')
dockerfile.volume([
 	'/home/rocketmq/logs/rocketmqlogs'
])
 
mqbroker = Services('mqbroker')
mqbroker.build(dockerfile).image('registry.netkiller.cn/rocketmq/mqbroker:4.9.2').container_name('mqbroker').ports(['10909:10909','10911:10911','10912:10912'])
mqbroker.command('mqbroker -n mqnamesrv:9876 -c /srv/rocketmq/conf/broker.conf')
mqbroker.volumes(['/tmp/logs:/home/rocketmq/logs/rocketmqlogs'])
 
composes = Composes('test')
composes.version('3.9')
composes.services(rocketmq)
composes.services(mqnamesrv)
composes.services(mqbroker)
 
 
# cat >> /srv/docker-entrypoint.sh <<'EOF'
# EOF
 
entrypoint='''#!/bin/sh
if [ "$1" = 'mqnamesrv' ]; then
	exec /srv/rocketmq/bin/mqnamesrv
fi
exec "$@"
'''
 
if __name__ == '__main__':
	try:
		docker = Docker({'DOCKER_HOST':'ssh://root@192.168.30.11','NAMESRV_ADDR':'localhost:9876'}) 
		docker.createfile('rocketmq/rocketmq/docker-entrypoint.sh',entrypoint)
		docker.environment(composes)
		docker.main()
	except KeyboardInterrupt:
		print ("Crtl+C Pressed. Shutting down.")

運(yùn)行

python3 demo.py -e test -b rocketmq

快速入門,首先我們參照這個(gè) docker-compose.yaml 腳本,轉(zhuǎn)換成 python 腳本。

version: '3.9'

services:

nginx:

container_name: nginx

environment:

- TZ=Asia/Shanghai

extra_hosts:

- db.netkiller.cn:127.0.0.1

- cache.netkiller.cn:127.0.0.1

- api.netkiller.cn:127.0.0.1

hostname: www.netkiller.cn

image: nginx:latest

ports:

- 80:80

- 443:443

restart: always

volumes:

- /tmp:/tmp

轉(zhuǎn)換成 python 語(yǔ)言之后

from netkiller.docker import *

service = Services('nginx')

service.image('nginx:latest')

service.container_name('nginx')

service.restart('always')

service.hostname('www.netkiller.cn')

service.extra_hosts(['db.netkiller.cn:127.0.0.1','cache.netkiller.cn:127.0.0.1','api.netkiller.cn:127.0.0.1'])

service.environment(['TZ=Asia/Shanghai'])

service.ports(['80:80','443:443'])

service.volumes(['/tmp:/tmp'])

# service.debug()

# print(service.dump())

compose = Composes('development')

compose.version('3.9')

compose.services(service)

# print (compose.debug())

print(compose.dump())

compose.save()

怎么樣,只是換了另一種寫法,并沒有難度。下面我們就系統(tǒng)學(xué)習(xí),如何使用 python 編排 docker 容器

實(shí)際上程序最終還是會(huì)轉(zhuǎn)化做 docker-compose 腳本執(zhí)行。這種寫法的有點(diǎn)是更靈活,你可以在程序中使用 if, while, 鏈接數(shù)據(jù)庫(kù),等等操作,可以做更復(fù)雜的容器編排。

安裝依賴庫(kù)

neo@MacBook-Pro-Neo ~ % pip install netkiller-devops

確認(rèn)是否安裝成功

neo@MacBook-Pro-Neo ~ % pip show netkiller-devops
Name: netkiller-devops
Version: 0.2.4
Summary: DevOps of useful deployment and automation
Home-page: https://github.com/oscm/devops
Author: Neo Chen
Author-email: netkiller@msn.com
License: BSD
Location: /usr/local/lib/python3.9/site-packages
Requires: pyttsx3, requests, redis, pyyaml
Required-by: 		

創(chuàng)建一個(gè) Services

from netkiller.docker import *
 
service =  Services('nginx')
service.image('nginx:latest')
service.container_name('nginx')
service.restart('always')
service.hostname('www.netkiller.cn')
service.extra_hosts(['db.netkiller.cn:127.0.0.1','cache.netkiller.cn:127.0.0.1','api.netkiller.cn:127.0.0.1'])
service.environment(['TZ=Asia/Shanghai'])
service.ports(['80:80','443:443'])
service.volumes(['/tmp:/tmp'])
# service.debug()
print(service.dump())		

運(yùn)行結(jié)果

nginx:
  container_name: nginx
  environment:
  - TZ=Asia/Shanghai
  extra_hosts:
  - db.netkiller.cn:127.0.0.1
  - cache.netkiller.cn:127.0.0.1
  - api.netkiller.cn:127.0.0.1
  hostname: www.netkiller.cn
  image: nginx:latest
  ports:
  - 80:80
  - 443:443
  restart: always
  volumes:
  - /tmp:/tmp		

來(lái)一個(gè)復(fù)雜的演示

for i in range(10) :
    cluster =  Services('nginx-'+str(i))
    cluster.image('nginx:latest').container_name('nginx-'+str(i)).restart('always').hostname('www'+str(i)+'.netkiller.cn')
    cluster.ports(['8{port}:80'.format(port=i)])
    print(cluster.dump())		

運(yùn)行結(jié)果

nginx-0:
  container_name: nginx-0
  hostname: www0.netkiller.cn
  image: nginx:latest
  ports:
  - 80:80
  restart: always
 
nginx-1:
  container_name: nginx-1
  hostname: www1.netkiller.cn
  image: nginx:latest
  ports:
  - 81:80
  restart: always
 
nginx-2:
  container_name: nginx-2
  hostname: www2.netkiller.cn
  image: nginx:latest
  ports:
  - 82:80
  restart: always
 
nginx-3:
  container_name: nginx-3
  hostname: www3.netkiller.cn
  image: nginx:latest
  ports:
  - 83:80
  restart: always
 
nginx-4:
  container_name: nginx-4
  hostname: www4.netkiller.cn
  image: nginx:latest
  ports:
  - 84:80
  restart: always
 
nginx-5:
  container_name: nginx-5
  hostname: www5.netkiller.cn
  image: nginx:latest
  ports:
  - 85:80
  restart: always
 
nginx-6:
  container_name: nginx-6
  hostname: www6.netkiller.cn
  image: nginx:latest
  ports:
  - 86:80
  restart: always
 
nginx-7:
  container_name: nginx-7
  hostname: www7.netkiller.cn
  image: nginx:latest
  ports:
  - 87:80
  restart: always
 
nginx-8:
  container_name: nginx-8
  hostname: www8.netkiller.cn
  image: nginx:latest
  ports:
  - 88:80
  restart: always
 
nginx-9:
  container_name: nginx-9
  hostname: www9.netkiller.cn
  image: nginx:latest
  ports:
  - 89:80
  restart: always		

創(chuàng)建 Composes

Services 對(duì)象創(chuàng)建服務(wù),讓服務(wù)工作還需要 Composes 對(duì)象。

from netkiller.docker import *
 
service =  Services('nginx')
service.image('nginx:latest')
service.container_name('nginx')
service.restart('always')
service.hostname('www.netkiller.cn')
service.extra_hosts(['db.netkiller.cn:127.0.0.1','cache.netkiller.cn:127.0.0.1','api.netkiller.cn:127.0.0.1'])
service.environment(['TZ=Asia/Shanghai'])
service.ports(['80:80','443:443'])
service.volumes(['/tmp:/tmp'])
 
compose = Composes('development')
compose.version('3.9')
compose.services(service)
# print (compose.debug())
print(compose.dump())
compose.save()
# compose.save('/tmp/docker-compose.yaml')		
 
運(yùn)行結(jié)果
services:
  nginx:
    container_name: nginx
    environment:
    - TZ=Asia/Shanghai
    extra_hosts:
    - db.netkiller.cn:127.0.0.1
    - cache.netkiller.cn:127.0.0.1
    - api.netkiller.cn:127.0.0.1
    hostname: www.netkiller.cn
    image: nginx:latest
    ports:
    - 80:80
    - 443:443
    restart: always
    volumes:
    - /tmp:/tmp
version: '3.9'		

這已經(jīng)是一個(gè)完善的 docker-compose 腳本了。使用 save 可以保存為 yaml 文件,這是使用 docker-compose -f development.yaml up 就可以啟動(dòng)容器了。

Composes 對(duì)象同時(shí)也攜帶了完善的 docker-compose 命令和參數(shù),用于自我管理容器。

compose.up() 創(chuàng)建容器
compose = Composes('development')
compose.version('3.9')
compose.services(service)
compose.up()
 
compose.start() 啟動(dòng)已存在的容器
compose = Composes('development')
compose.version('3.9')
compose.services(service)
compose.start()
 
compose.stop() 停止已存在的容器
compose = Composes('development')
compose.version('3.9')
compose.services(service)
compose.stop()
 
compose.restart() 重啟已存在的容器
compose = Composes('development')
compose.version('3.9')
compose.services(service)
compose.restart()
 
compose.rm() 銷毀已存在的容器
compose = Composes('development')
compose.version('3.9')
compose.services(service)
compose.rm()
 
compose.logs() 查看容器日志
compose = Composes('development')
compose.version('3.9')
compose.services(service)
compose.logs()
 
compose.ps() 查看容器運(yùn)行狀態(tài)
compose = Composes('development')
compose.version('3.9')
compose.services(service)
compose.ps()

容器管理

Docker 對(duì)象是讓我們擺脫 docker-compose 這個(gè)命令,它將接管 docker-compose 這個(gè)命令,進(jìn)行自我管理。

#!/usr/bin/python3
#-*- coding: utf-8 -*-
##############################################
# Home	: http://netkiller.github.io
# Author: Neo <netkiller@msn.com>
# Upgrade: 2021-09-05
##############################################
try:
	import os,  sys
	module = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
	sys.path.insert(0,module)
	from netkiller.docker import *
except ImportError as err:
	print("%s" %(err))
 
nginx =  Services('nginx')
nginx.image('nginx:latest')
nginx.container_name('nginx')
nginx.restart('always')
nginx.hostname('www.netkiller.cn')
nginx.environment(['TA=Asia/Shanghai'])
nginx.ports(['80:80'])
 
compose = Composes('development')
compose.version('3.9')
compose.services(nginx)
compose.workdir('/tmp/compose')
 
if __name__ == '__main__':
	try:
		docker = Docker()
		docker.environment(compose)
		docker.main()
	except KeyboardInterrupt:
		print ("Crtl+C Pressed. Shutting down.")		
 
運(yùn)行結(jié)果
neo@MacBook-Pro-Neo ~ % python3 docker.py
Usage: docker.py [options] up|rm|start|stop|restart|logs|top|images|exec <service>
 
Options:
  -h, --help         show this help message and exit
  --debug            debug mode
  -d, --daemon       run as daemon
  --logfile=LOGFILE  logs file.
  -l, --list         following logging
  -f, --follow       following logging
  -c, --compose      show docker compose
  -e, --export       export docker compose
 
Homepage: http://www.netkiller.cn       Author: Neo <netkiller@msn.com>		

Docker 對(duì)象提供了與 docker-compose 對(duì)等的參數(shù),用法也基本相通。例如

python3 docker.py up = docker-compose up
python3 docker.py up -d nginx = docker-compose up -d nginx
python3 docker.py restart nginx = docker-compose restart nginx
 
python3 docker.py ps = docker-compose ps
python3 docker.py logs nginx = docker-compose logs nginx

使用 -c 可以查看 compose yaml 腳本,使用 -e 可以導(dǎo)出 docker compose yaml

演示例子

Redis 主從配置

例18.1.Redis Master/Slave

from netkiller.docker import *
 
image = 'redis:latest'
requirepass='11223344'
 
compose = Composes('redis-master-slave')
compose.version('3.9')
 
master =  Services('master')
master.image(image)
master.container_name('master')
master.restart('always')
master.environment(['TZ=Asia/Shanghai'])
master.ports('6379:6379')
master.volumes(['/tmp/master:/data'])
master.sysctls(['net.core.somaxconn=1024'])
master.command([
	'--requirepass '+requirepass,
	'--appendonly yes'])
# master.debug()
# print(master.dump())
compose.services(master)
 
 
for i in range(5) :
    slave =  Services('slave-'+str(i))
    slave.image(image).container_name('slave-'+str(i)).restart('always')
    slave.ports(['638{port}:6379'.format(port=i)]).environment(['TZ=Asia/Shanghai'])
    slave.volumes(['/tmp/slave{n}:/data'.format(n=i)])
    slave.sysctls(['net.core.somaxconn=1024']).command([
        '--slaveof master 6379',
        '--masterauth '+requirepass,
        '--requirepass ' + requirepass,
        '--appendonly yes'
    ])
 
    # print(cluster.dump())
    compose.services(slave)
 
# print (compose.debug())
print(compose.dump())
# compose.save()
compose.up()					

以上就是使用Python編排Dockerfile的代碼詳解的詳細(xì)內(nèi)容,更多關(guān)于Python編排Dockerfile的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • torchxrayvision包安裝過(guò)程(附pytorch1.6cpu版安裝)

    torchxrayvision包安裝過(guò)程(附pytorch1.6cpu版安裝)

    這篇文章主要介紹了torchxrayvision包安裝過(guò)程(附pytorch1.6cpu版安裝),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • 基于Python編寫一個(gè)桌面時(shí)鐘屏保

    基于Python編寫一個(gè)桌面時(shí)鐘屏保

    這篇文章主要為大家詳細(xì)介紹了如何基于Python編寫一個(gè)桌面時(shí)鐘屏保效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-12-12
  • pyshp創(chuàng)建shp點(diǎn)文件的方法

    pyshp創(chuàng)建shp點(diǎn)文件的方法

    今天小編就為大家分享一篇pyshp創(chuàng)建shp點(diǎn)文件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • python數(shù)據(jù)分析之實(shí)現(xiàn)地圖數(shù)據(jù)繪制

    python數(shù)據(jù)分析之實(shí)現(xiàn)地圖數(shù)據(jù)繪制

    這篇文章主要為大家詳細(xì)介紹了python數(shù)據(jù)分析中如何實(shí)現(xiàn)地圖數(shù)據(jù)繪制,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-12-12
  • 如何用Python實(shí)現(xiàn)自動(dòng)發(fā)送微博

    如何用Python實(shí)現(xiàn)自動(dòng)發(fā)送微博

    大家好,本篇文章主要講的是如何用Python實(shí)現(xiàn)自動(dòng)發(fā)送微博,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏
    2022-01-01
  • python免殺技術(shù)shellcode的加載與執(zhí)行

    python免殺技術(shù)shellcode的加載與執(zhí)行

    本文主要介紹了python免殺技術(shù)shellcode的加載與執(zhí)行,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 解決Tensorflow占用GPU顯存問(wèn)題

    解決Tensorflow占用GPU顯存問(wèn)題

    今天小編就為大家分享一篇解決Tensorflow占用GPU顯存問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-02-02
  • Python過(guò)濾序列元素的方法

    Python過(guò)濾序列元素的方法

    這篇文章主要介紹了Python過(guò)濾序列元素的方法,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Python結(jié)合turtle簡(jiǎn)單開發(fā)一個(gè)煙花小工具

    Python結(jié)合turtle簡(jiǎn)單開發(fā)一個(gè)煙花小工具

    這篇文章主要為大家詳細(xì)介紹了Python如何利用turtle模塊實(shí)現(xiàn)的簡(jiǎn)單的煙花效果展示小工具,文章的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下
    2025-12-12
  • 利用Python爬取微博數(shù)據(jù)生成詞云圖片實(shí)例代碼

    利用Python爬取微博數(shù)據(jù)生成詞云圖片實(shí)例代碼

    這篇文章主要給大家介紹了關(guān)于利用Python爬取微博數(shù)據(jù)生成詞云圖片的相關(guān)資料,文中通過(guò)示例代碼介紹非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用python具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-08-08

最新評(píng)論

会昌县| 于田县| 浙江省| 广宗县| 淮安市| 通山县| 湘潭县| 云梦县| 苏尼特左旗| 怀化市| 丹巴县| 遵义市| 聊城市| 石楼县| 英吉沙县| 永济市| 西畴县| 井研县| 淳化县| 新营市| 大渡口区| 昭平县| 吉安县| 格尔木市| 都安| 南部县| 桦川县| 鹤山市| 夏河县| 油尖旺区| 盈江县| 柘荣县| 夹江县| 乌苏市| 彭泽县| 惠来县| 报价| 左云县| 盐城市| 东港市| 崇明县|