Docker-Compose環(huán)境搭建和部署SpringBoot項(xiàng)目

前言

fighting


Docker使用nsenter工具進(jìn)入容器

1.下載nsenter工具

wget https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.33/util-linux-2.33.tar.gz

2.解壓util-linux-2.33.tar.gz

tar -zxvf util-linux-2.33.tar.gz

3.進(jìn)入cd util-linux-2.33目錄揖盘,輸入./configure --without-ncurses命令進(jìn)行check

4.輸入make nsenter,對nsenter進(jìn)行編譯

5.復(fù)制nsenter到/usr/local/bin

cp nsenter /usr/local/bin

6.查看nsenter的版本

[root@localhost util-linux-2.33]# nsenter --version
nsenter选调,來自 util-linux 2.33

7.docker inspect命令會提取出容器或者鏡像最頂層的元數(shù)據(jù)违施,我們可以通過PID=$(docker inspect --format "{{ .State.Pid}}" <container id>)獲取容器的進(jìn)程id琅翻,然后再通過nsenter --target $PID --mount --uts --ipc --net --pid進(jìn)入到容器中法精。

8.獲取12dfffb03859容器的pid,docker inspect --format "{{.State.Pid}}" 12dfffb03859

[root@localhost util-linux-2.33]# docker inspect --format "{{.State.Pid}}" 12dfffb03859
1894

9.nsenter --target 1894 --mount --uts --ipc --net --pid進(jìn)入容器.

10.我們把以上繁瑣的操作寫成docker-enter.sh

#!/bin/sh

if [ -e $(dirname "$0")/nsenter ]; then
  # with boot2docker, nsenter is not in the PATH but it is in the same folder
  NSENTER=$(dirname "$0")/nsenter
else
  NSENTER=nsenter
fi

if [ -z "$1" ]; then
  echo "Usage: `basename "$0"` CONTAINER [COMMAND [ARG]...]"
  echo ""
  echo "Enters the Docker CONTAINER and executes the specified COMMAND."
  echo "If COMMAND is not specified, runs an interactive shell in CONTAINER."
else
  PID=$(docker inspect --format "{{.State.Pid}}" "$1")
  if [ -z "$PID" ]; then
    exit 1
  fi
  shift

  OPTS="--target $PID --mount --uts --ipc --net --pid --"

  if [ -z "$1" ]; then
    # No command given.
    # Use su to clear all host environment variables except for TERM,
    # initialize the environment variables HOME, SHELL, USER, LOGNAME, PATH,
    # and start a login shell.
#"$NSENTER" $OPTS su - root
"$NSENTER" $OPTS /bin/su - root
  else
    # Use env to clear all host environment variables.
    "$NSENTER" $OPTS env --ignore-environment -- "$@"
  fi
fi

11.在/etc/profile設(shè)置別名alias docker-enter=/usr/local/docker-sh/docker-enter.sh,然后source /etc/profile保存配置,再alias docker-enter查看設(shè)置別名是否生效

image.png

  1. docker-enter 9393ed00b852,進(jìn)入容器成功印蔬。
    image.png

13.感覺用nsenter有點(diǎn)麻煩,其實(shí)可以用docker exec -it 12dfffb03859 /bin/bash脱衙,如果出現(xiàn)stat /bin/bash: no such file or directory的錯誤侥猬,這是由于容器中的PATH 路徑問題,使用/bin/su 即可捐韩。

[root@localhost util-linux-2.33]# docker exec -it 12dfffb03859 /bin/su
/ # ls
bin       etc       lib64     proc      sbin      tmp
demo.jar  home      media     root      srv       usr
dev       lib       mnt       run       sys       var
/ # 

Docker Compose介紹

Dockerfile可以讓用戶管理一個單獨(dú)的應(yīng)用容器退唠;而Docker Compose則允許用戶在一個模板(yaml格式)中定義一組相關(guān)聯(lián)的應(yīng)用容器(被稱為一個project,即項(xiàng)目),例如一個web服務(wù)容器再加上redis服務(wù)容器荤胁,nginx服務(wù)容器等瞧预。

docker compose.png

搭建Docker-Compose環(huán)境

1.下載安裝docker-compose

#下載
sudo curl -L https://github.com/docker/compose/releases/download/1.20.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
#安裝
chmod +x /usr/local/bin/docker-compose
#查看版本
docker-compose version
image.png

2.下載docker補(bǔ)全命令

#安裝
yum install bash-completion
#下載docker-compose腳本
curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose
image.png

Docker-compose部署Python Flask項(xiàng)目

1.創(chuàng)建app.py

import time
import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
        retries = 5
        while True:
                try:
                        return cache.incr('hits')
                except redis.exceptions.ConnectionError as exc:
                        if retries == 0:
                                raise exc
                        retries -= 1
                        time.sleep(0.5)


@app.route('/')
def hello():
        count = get_hit_count()
        return 'hello python! i have been seen {} times\n'.format(count)

if __name__ == "__main__":
        app.run(host="0.0.0.0", debug=True)

2.同目錄下創(chuàng)建requirements.txt文件,添加項(xiàng)目依賴的python包

flask
redis

3.創(chuàng)建網(wǎng)絡(luò)cmazxiaoma_net

[root@localhost python-flask]# docker network create cmazxiaoma_net
392423d2779c8ef18d1c4bbc1d1a9142ae1b2fc63bc73e716bdd9e76013387cf
[root@localhost python-flask]# docker network ls

4.創(chuàng)建Dockerfile

FROM python:3.4-alpine
maintainer cmazxiaoma
ADD . /python-code #將當(dāng)前目錄的所有文件拷貝至/python-code
WORKDIR /python-code #設(shè)置工作目錄為/python-code
RUN pip install -r requirements.txt #安裝python依賴包
CMD ["python", "app.py"] #容器啟動時允許app.py

5.創(chuàng)建docker-compose.yml

version: '2'
services:
        web:
                build: . # 構(gòu)建容器
                ports:
                        - "9021:5000"
                volumes:
                        - .:/python-code  #將當(dāng)前目錄掛載到web容器中的/python-code
                depends_on: # redis服務(wù)先啟動
                        - redis
                networks:
                        - custom_net
        redis:
                image:  "redis:alpine"
                container_name: redis_container
                restart:         always
                ports:
                        - 6380:6379
                expose:
                        - 6379
                networks:
                        - custom_net
networks:
        custom_net:
                external:
                        name: cmazxiaoma_net #設(shè)置網(wǎng)絡(luò)
  1. 把項(xiàng)目目錄添加到selinux白名單
chcon -Rt svirt_sandbox_file_t python-flask

7.docker-compose up -d后臺啟動應(yīng)用

image.png

image.png

8.docker-compose run web ping redis測試同一應(yīng)用下的redis和web服務(wù)是否能ping通寨蹋。

image.png

9.docker-compose相關(guān)的命令如下:

#查看幫助
docker-compose -h

# -f  指定使用的 Compose 模板文件
# 默認(rèn)為 docker-compose.yml松蒜,可以多次指定扔茅。
docker-compose -f docker-compose.yml up -d 

#啟動所有容器已旧,-d 將會在后臺啟動并運(yùn)行所有的容器
docker-compose up -d

#停用移除所有容器以及網(wǎng)絡(luò)相關(guān)
docker-compose down

#查看服務(wù)容器的輸出
docker-compose logs

#列出項(xiàng)目中目前的所有容器
docker-compose ps

#構(gòu)建(重新構(gòu)建)項(xiàng)目中的服務(wù)容器。服務(wù)容器一旦構(gòu)建后召娜,將會帶上一個標(biāo)記名.
#例如對于 web 項(xiàng)目中的一個 db 容器运褪,可能是 web_db。
#可以隨時在項(xiàng)目目錄下運(yùn)行 docker-compose build 來重新構(gòu)建服務(wù)
docker-compose build

# 不帶緩存的構(gòu)建玖瘸。
docker-compose build --no-cache

#拉取服務(wù)依賴的鏡像
docker-compose pull

#重啟項(xiàng)目中的服務(wù)
docker-compose restart

#刪除所有(停止?fàn)顟B(tài)的)服務(wù)容器秸讹。
#推薦先執(zhí)行 docker-compose stop 命令來停止容器。
docker-compose rm 

#在指定服務(wù)上執(zhí)行一個命令雅倒。
docker-compose run ubuntu ping docker.com

#設(shè)置指定服務(wù)運(yùn)行的容器個數(shù)璃诀。通過 service=num 的參數(shù)來設(shè)置數(shù)量
docker-compose scale web=3 db=2

#啟動已經(jīng)存在的服務(wù)容器。
docker-compose start

#停止已經(jīng)處于運(yùn)行狀態(tài)的容器蔑匣,但不刪除它劣欢。
#通過 docker-compose start 可以再次啟動這些容器。
docker-compose stop

Docker-compose部署SpringBoot項(xiàng)目

1.項(xiàng)目目錄


目錄結(jié)構(gòu).png

2.nginx.conf

server {
    listen 80;
    charset utf-8;
    access_log off;

    location / {
        proxy_pass http://app:8080;
        proxy_set_header Host $host:$server_port;
        proxy_set_header X-Forwarded-Host $server_name;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /static {
        access_log   off;
        expires      30d;

        alias /app/static;
    }
}
  1. docker-compose.yml
version: '3'
services:
  nginx:
   container_name: v-nginx
   image: nginx:1.13
   restart: always
   ports:
   - 81:80
   - 444:443
   volumes:
   - ./nginx/conf.d:/etc/nginx/conf.d

  mysql:
   container_name: v-mysql
   image: mysql/mysql-server:5.7
   environment:
    MYSQL_DATABASE: root
    MYSQL_ROOT_PASSWORD: root
    MYSQL_ROOT_HOST: '%'
   ports:
   - "3308:3306"
   restart: always

  app:
    restart: always
    build: .
    working_dir: /jenkins-demo
    volumes:
      - .:/jenkins-demo
      - ~/.m2:/root/.m2
    expose:
      - "8080"
    depends_on:
      - nginx
      - mysql
    command: mvn clean spring-boot:run -Dspring-boot.run.profiles=docker

4.Dockerfile

FROM maven:3.5-jdk-8
MAINTAINER cmazxiaoma
WORKDIR /jenkins-demo
RUN mkdir /root/.m2
COPY settings.xml /root/.m2/
RUN mkdir -p /usr/local/mvn-resource/repository && \
cd /usr/local/mvn-resource/repository && \
echo $(mvn --version) && \
mvn help:system && \
chmod 777 /usr/local/mvn-resource && \
chmod 777 /jenkins-demo && \

5.setting.xml中需要更改的配置


repository.png
alimaven.png

6.application-docker.properties

server.port=8080
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://mysql:3306/docker-compose?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect

spring.resources.add-mappings=true

7.添加linux規(guī)則裁良,把要掛載的目錄~/.m2添加到selinux白名單凿将。

chcon -Rt svirt_sandbox_file_t ~/.m2
chcon -Rt svirt_sandbox_file_t /jenkins-demo

8.啟動應(yīng)用docker-compose up,瀏覽界面成功价脾!

image.png

nginx上面的圖片.png

Docker-Compose順序問題

docker-compose 雖然可以通過 depends_on來定義服務(wù)啟動的順序牧抵,但是無法確定服務(wù)是否啟動完成。因此會出現(xiàn)這樣一個現(xiàn)象,redis服務(wù)啟動比較慢犀变,當(dāng)項(xiàng)目已經(jīng)啟動起來妹孙,但是redis還沒有初始化好,這樣當(dāng)項(xiàng)目連接redis的時候就會出現(xiàn)連接數(shù)據(jù)庫的異常获枝。

針對這樣的問題涕蜂,有兩種解決方案:

  • 足夠的容錯和重試機(jī)制,比如連接redis映琳,在初次連接不上的時候机隙,服務(wù)消費(fèi)者可以不斷重試,直到連接上服務(wù)萨西。也就是在服務(wù)中定義:restart: always

  • 同步等待有鹿,使用wait-for-it.sh或者其他shell腳本將當(dāng)前服務(wù)啟動阻塞,直到被依賴的服務(wù)加載完畢谎脯。


參考文章

1.Spring Boot 2.0(五):Docker Compose + Spring Boot + Nginx + Mysql 實(shí)踐
2.Docker -v 對掛載的目錄沒有權(quán)限 Permission denied解決辦法


尾言

最近很焦慮葱跋,發(fā)現(xiàn)自己很多東西都不會。不要擾亂他人的心志源梭,不要動搖自己的決心娱俺。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市废麻,隨后出現(xiàn)的幾起案子荠卷,更是在濱河造成了極大的恐慌,老刑警劉巖烛愧,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件油宜,死亡現(xiàn)場離奇詭異,居然都是意外死亡怜姿,警方通過查閱死者的電腦和手機(jī)慎冤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沧卢,“玉大人蚁堤,你說我怎么就攤上這事〉粒” “怎么了披诗?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長熟空。 經(jīng)常有香客問我藤巢,道長,這世上最難降的妖魔是什么息罗? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任掂咒,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘绍刮。我一直安慰自己温圆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布孩革。 她就那樣靜靜地躺著岁歉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪膝蜈。 梳的紋絲不亂的頭發(fā)上锅移,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天,我揣著相機(jī)與錄音饱搏,去河邊找鬼非剃。 笑死,一個胖子當(dāng)著我的面吹牛推沸,可吹牛的內(nèi)容都是我干的备绽。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼鬓催,長吁一口氣:“原來是場噩夢啊……” “哼肺素!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起宇驾,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤倍靡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后飞苇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體菌瘫,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜗顽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年布卡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雇盖。...
    茶點(diǎn)故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡忿等,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出崔挖,到底是詐尸還是另有隱情贸街,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布狸相,位于F島的核電站薛匪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏脓鹃。R本人自食惡果不足惜逸尖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧娇跟,春花似錦岩齿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吃谣,卻和暖如春乞封,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背岗憋。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工歌亲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人澜驮。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓陷揪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親杂穷。 傳聞我的和親對象是個殘疾皇子悍缠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容