相信點進來看這篇文章的同窗們已經對 Docker Dompose 有必定的瞭解了,下面,咱們拿最簡單的例子來介紹如何使用 Docker Compose 來管理項目。
本文例子:
一個應用服務( Spring Boot 的 jar 包)、 Mysql 服務和 Redis 服務。在每次啓動,咱們要先將 Mysql 容器和 Redis 容器啓動起來,再將應用容器運行起來,這其中還不要忘了在建立應用容器時將容器網絡鏈接到 MySQL 容器和 Redis 容器上,以便應用鏈接上它們並進行數據交換。html
爲了方便進行管理和遷移,咱們建議將 Docker Compose 項目與搭建一個軟件開發項目同樣,將項目的內容彙集到一個文件目錄中,下面是一個比較通用的項目結構:java
└─ project ├─ app ├─ compose │ └─ docker-compose.yml ├─ mysql │ └─ my.cnf ├─ redis └─ redis.conf
在這個目錄結構中,區分了 5 個頂層目錄:mysql
爲了更方便在開發過程當中對 MySQL、Redis 程序自己管理,因此咱們會將它們的核心配置放置到項目裏,再經過掛載的方式映射到容器中。
這樣一來,咱們就能夠直接在咱們宿主操做系統裏直接修改這些配置,無須再進入到容器中了。
基於此,咱們在完成目錄的設計以後,首要解決的問題就是準備好這些程序中會常常變更的配置,並把它們放置在程序對應的目錄之中。git
咱們經常使用下列幾種方式來得到程序的配置文件:github
咱們先找到 MySQL 文檔中關於配置文件的參考,也就是下面這個地址:
https://dev.mysql.com/doc/refman/5.7/en/server-options.html
咱們根據這些內容,選取跟咱們程序運行有影響的幾項須要修改的參數,編寫成 MySQL 的配置文件。web
# ./mysql/my.cnf [mysqld_safe] pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock nice = 0 [mysqld] skip-host-cache skip-name-resolve explicit_defaults_for_timestamp bind-address = 0.0.0.0 port = 3306 user = mysql pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock log-error = /var/log/mysql/error.log basedir = /usr datadir = /var/lib/mysql tmpdir = /tmp sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES lc-messages-dir = /usr/share/mysql symbolic-links = 0
在 Redis 源代碼中,就包含了一份默認的配置文件,咱們能夠基於上面作修改:
github上面的連接:https://github.com/antirez/redis/blob/3.2/redis.conf
其中我修改了最主要的密碼:redis
# ./redis/redis.conf ##... ################################## SECURITY ################################### # Require clients to issue AUTH <PASSWORD> before processing any other # commands. This might be useful in environments in which you do not trust # others with access to the host running redis-server. # # This should stay commented out for backward compatibility and because most # people do not need auth (e.g. they run their own servers). # # Warning: since Redis is pretty fast an outside user can try up to # 150k passwords per second against a good box. This means that you should # use a very strong password otherwise it will be very easy to break. # 鏈接Redis須要的密碼 requirepass Redis123 ##...
這個是基於java:8鏡像提交的webapp鏡像,你們可參考上一篇文章:https://blog.csdn.net/Howinfun/article/details/102514099spring
docker-compose.yml 文件在compose文件夾下,下面是我本身根據需求編寫的:sql
version: "3" services: redis: image: redis:3.2 container_name: app_redis volumes: - ../redis/redis.conf:/etc/redis/redis.conf:ro - ../redis/data:/data command: - redis-server - /etc/redis/redis.conf ports: - 6379:6379 mysql: image: mysql:5.7 container_name: app_mysql volumes: - ../mysql/my.cnf:/etc/mysql/my.cnf:ro - ../mysql/data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: 123456 ports: - 3306:3306 webapp: build: ../app container_name: app_web depends_on: - mysql - redis ports: - "8888:8888"
稍微講解一下:
version:版本號,最新爲3
services:Compose項目的服務配置
redis:docker
mysql:
webapp:
在這個項目裏,我將 Redis 和 MySQL 的數據存儲目錄,也就是 Redis 容器中的 /data 目錄和 MySQL 容器中的 /var/lib/mysql 目錄經過掛載的方式綁定到了宿主機上的目錄中。 這麼作的目的是爲了讓 Redis 和 MySQL 的數據可以持久化存儲,避免咱們在建立和移除容器時形成數據的流失。
同時,這種將數據掛載出來的方法,能夠直接方便咱們打包數據並傳送給其餘開發者,方便開發過程當中進行聯調。
docker-compose up 命令相似於 Docker Engine 中的 docker run,它會根據 docker-compose.yml 中配置的內容,建立全部的容器、網絡、數據卷等等內容,並將它們啓動。與 docker run 同樣,默認狀況下 docker-compose up 會在「前臺」運行,咱們能夠用 -d 選項使其「後臺」運行。事實上,咱們大多數狀況都會加上 -d 選項。
docker-compose -p appweb -f ./compose/docker-compose.yml up -d
命令參數:
[root@izwz90lvzs7171wgdhul8az project2]# docker-compose -p appweb -f ./compose/docker-compose.yml up -d Building webapp Step 1/5 : FROM java:8 ---> d23bdf5b1b1b Step 2/5 : MAINTAINER Howinfun ---> Using cache ---> f72d0468f1ff Step 3/5 : VOLUME /tmp ---> Using cache ---> 902b3df17b06 Step 4/5 : ADD app.jar /root/docker_test/app.jar ---> 511f44917a82 Step 5/5 : ENTRYPOINT ["nohup","java","-jar","/root/docker_test/app.jar",">","/root/docker_test/app.log","&"] ---> Running in 4825ec9daf24 Removing intermediate container 4825ec9daf24 ---> 5e009b2fc6ae Successfully built 5e009b2fc6ae Successfully tagged appweb_webapp:latest WARNING: Image for service webapp was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`. Creating app_mysql ... done Creating app_redis ... done Creating app_web ... done
查看建立的鏡像:
[root@izwz90lvzs7171wgdhul8az project2]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE appweb_webapp latest 5e009b2fc6ae 45 seconds ago 686MB mysql 5.7 383867b75fd2 4 weeks ago 373MB redis 3.2 87856cc39862 12 months ago 76MB
查看正在啓動的容器:
[root@izwz90lvzs7171wgdhul8az project2]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ccaa96d508d1 appweb_webapp "nohup java -jar /ro?? About a minute ago Up About a minute 0.0.0.0:8888->8888/tcp app_web 790629b5e7d0 mysql:5.7 "docker-entrypoint.s?? About a minute ago Up About a minute 0.0.0.0:3306->3306/tcp, 33060/tcp app_mysql 610d0b89c267 redis:3.2 "docker-entrypoint.s?? About a minute ago Up About a minute 0.0.0.0:6379->6379/tcp app_redis
容器啓動後,咱們嘗試使用postman或者其餘http工具去訪問部署在容器中的應用接口。
咱們都知道,使用 Docker 打包鏡像,咱們能夠在任意的環境下部署和運行項目,Docker 的容器可以很輕鬆的運行在開發者本地的電腦,數據中心的物理機或虛擬機,雲服務商提供的雲服務器,甚至是混合環境中。
可是,這裏的每個環境的IP地址但是不同,並且,應用服務連接的Mysql數據庫,或者Redis緩存那一定是要和部署環境的IP地址一一對應的,那麼難道咱們還須要每次都去修改配置文件的IP嗎?
答案是:不用的!
在 Docker Compose 裏,咱們能夠爲整個應用系統設置一個或多個網絡。要使用網絡,咱們必須先聲明網絡。聲明網絡的配置一樣獨立於 services 存在,是位於根配置下的 networks 配置。
下面咱們嘗試在docker-compose.yml中添加網絡配置。
version: "3" services: redis: image: redis:3.2 container_name: app_redis volumes: - ../redis/redis.conf:/etc/redis/redis.conf:ro - ../redis/data:/data command: - redis-server - /etc/redis/redis.conf ports: - 6379:6379 networks: - appnet mysql: image: mysql:5.7 container_name: app_mysql volumes: - ../mysql/my.cnf:/etc/mysql/my.cnf:ro - ../mysql/data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: 123456 ports: - 3306:3306 networks: - appnet webapp: build: ../app container_name: app_web depends_on: - mysql - redis ports: - "8888:8888" networks: - appnet networks: appnet: driver: bridge
能夠看到,咱們在docker-compose.yml文件的最下面添加了關於網絡的配置。網絡名爲appnet,網絡驅動爲 Bridge。
Bridge 網絡是 Docker 容器的默認網絡驅動,簡而言之其就是經過網橋來實現網絡通信。
而後在每一個服務的下面都配置上服務所在的網格,就是上面的 appnet 了。
接下來,修改 application.properties 中的IP,改成容器名或者服務名做爲網絡地址。
例如個人配置文件要將 MySql 和 Redis 的IP,改成各自服務的容器名:
#Mysql spring.datasource.url=jdbc\:mysql\://app_mysql\:3306/test?useUnicode\=true&characterEncoding\=utf-8&allowMultiQueries=true&&useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=123456 #Redis spring.redis.host=app_redis spring.redis.password=Redis123.. spring.redis.database=1
與 docker-compose up 相反,docker-compose down 命令用於中止全部的容器,並將它們刪除,同時消除網絡等配置內容,也就是幾乎將這個 Docker Compose 項目的全部影響從 Docker 中清除。
docker-compose -p appweb -f ./compose/docker-compose.yml down --rmi all
命令參數:
[root@izwz90lvzs7171wgdhul8az project2]# docker-compose -p appweb -f ./compose/docker-compose.yml down --rmi all Stopping app_web ... done Stopping app_mysql ... done Stopping app_redis ... done Removing app_web ... done Removing app_mysql ... done Removing app_redis ... done Removing network appweb_default Removing image redis:3.2 Removing image mysql:5.7 Removing image appweb_webapp
注意:若是在使用 up 命令時指定了項目名,而在 down 命令時沒有指定項目名會報錯:
[root@izwz90lvzs7171wgdhul8az project2]# docker-compose -f ./compose/docker-compose.yml down Removing network compose_default WARNING: Network compose_default not found.
docker-compose -p appweb -f ./compose/docker-compose.yml up -d
命令參數:
[root@izwz90lvzs7171wgdhul8az project2]# docker-compose -p appweb -f ./compose/docker-compose.yml up -d Creating network "appweb_appnet" with driver "bridge" Pulling redis (redis:3.2)... 3.2: Pulling from library/redis f17d81b4b692: Pull complete b32474098757: Pull complete 8980cabe8bc2: Pull complete 58af19693e78: Pull complete a977782cf22d: Pull complete 9c1e268980b7: Pull complete Digest: sha256:7b0a40301bc1567205e6461c5bf94c38e1e1ad0169709e49132cafc47f6b51f3 Status: Downloaded newer image for redis:3.2 Pulling mysql (mysql:5.7)... 5.7: Pulling from library/mysql 8f91359f1fff: Pull complete 6bbb1c853362: Pull complete e6e554c0af6f: Pull complete f391c1a77330: Pull complete 414a8a88eabc: Pull complete fee78658f4dd: Pull complete 9568f6bff01b: Pull complete 76041efb6f83: Pull complete ea54dbd83183: Pull complete 566857d8f022: Pull complete 01c09495c6e7: Pull complete Digest: sha256:f7985e36c668bb862a0e506f4ef9acdd1254cdf690469816f99633898895f7fa Status: Downloaded newer image for mysql:5.7 Building webapp Step 1/5 : FROM java:8 ---> d23bdf5b1b1b Step 2/5 : MAINTAINER Howinfun ---> Using cache ---> f72d0468f1ff Step 3/5 : VOLUME /tmp ---> Using cache ---> 902b3df17b06 Step 4/5 : ADD app.jar /root/docker_test/app.jar ---> 674b9e9f9766 Step 5/5 : ENTRYPOINT ["nohup","java","-jar","/root/docker_test/app.jar",">","/root/docker_test/app.log","&"] ---> Running in 428e426ccede Removing intermediate container 428e426ccede ---> f0f5e8bf51cb Successfully built f0f5e8bf51cb Successfully tagged appweb_webapp:latest WARNING: Image for service webapp was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`. Creating app_mysql ... done Creating app_redis ... done Creating app_web ... done [root@izwz90lvzs7171wgdhul8az project2]#
上面咱們能夠很清楚的看到,啓動項目時第一件事情就是建立項目配置的網絡 appnet 了。
最後咱們再嘗試測試一下接口,能夠發現是沒有問題的。那麼就是說,如今這個項目打包到哪裏均可以運行了,而不用理會不一樣環境下的不一樣網絡。
到這裏,利用 Docker Compose 搭建 Spring Boot 運行環境已經所有完成。其實只要掌握了這個搭建方法,之後不論是搭建 Spring Cloud 微服務,甚至是其餘語言,例如 Python、Go等,方法都是同樣的,最主要的是服務的配置和之間的依賴,即編寫 Docker Compose 的定義文件 docker-compose.yml。