<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      用Docker搭建LNMP

      程序員經常會說的一句話:在我的機器上是正常的,肯定是你的機器有問題。因此,Docker誕生了,它把應用所需要的一切東西都打包,從而可以很方便地進行部署。

      Docker 的主要用途,目前有三大類:

      1. 提供一次性的環境。比如,本地測試他人的軟件、持續集成的時候提供單元測試和構建的環境。
      2. 提供彈性的云服務。因為 Docker 容器可以隨開隨關,很適合動態擴容和縮容。
      3. 組建微服務架構。通過多個容器,一臺機器可以跑多個服務,因此在本機就可以模擬出微服務架構。

      下面開始來體驗Docker,操作系統為win10,Docker的安裝請參考官方文檔,這里略過。

      Hello World

      官方提供了一個程序員最喜歡的hello world鏡像,我們就以此來開始Docker之旅,感受Docker的強大之處吧:

      docker run hello-world
      

      如果你看到輸出Hello from Docker!,恭喜你,Docker安裝成功了。

      image和container

      鏡像和容器可以理解為面向對象里面的類和對象。

      上面的例子是直接拿官方的鏡像來跑,我們也可以在官方鏡像的基礎上加工,來構建新的鏡像,當然也可以不基于任何鏡像來構建。

      所有內容(代碼、軟件、環境等)都可以通過Dockerfile配置來構建image,通過image可以運行具體的container實例。

      查看鏡像列表:docker image ls

      查看容器列表:docker container ls

      如果要查看完整的列表,在ls后面加個-a選項就好了:docker container ls -a

      裝個Linux

      下面加點難度,裝個Linux,alpine體積小,很多開源鏡像也是以它為基礎(比如Nginx),很適合用來體驗:

      docker run -it --rm alpine
      

      發現run后面多了幾個選項,其中-it其實是-i -t的縮寫,即interactive terminal,交互式終端的意思,不加這個我們是進不到容器的交互式終端的。

      加了--rm,表示在容器退出后會自動刪除容器,我們這里是為了體驗,希望用完之后不要占用磁盤空間,所以加了刪除選項,注意這里不是刪除鏡像,刪除的是容器。

      現在我們進入到alpine系統的終端了,輸入命令查看系統版本試試:

      cat /etc/os-release
      

      體驗完畢,這時候只要輸入exit按下回車就可以退出容器了。

      如果想運行容器的時候直接輸出系統版本,可以這么玩:

      docker run --rm alpine cat /etc/os-release
      

      在鏡像名后面直接跟上你想運行的命令,輸出系統版本信息以后容器就自動關閉并刪除了。

      運行PHP

      好了,現在Linux系統裝好了,直覺告訴我,如果要跑PHP,我們就直接進到剛剛那個alpine容器里面安裝就好了,那么不好意思,你的姿勢錯了。先不解釋,先看看正確姿勢:

      我們先在CLI模式下體驗PHP,在這之前,我們可以看看官方的php-cli:7.2鏡像的Dockerfile是怎么定義的:

      FROM debian:stretch-slim
      ...此處省略若干行...
      

      FROM指定基于哪個鏡像,也可以不基于任何鏡像:FROM scratch,比如官方的alpine的Dockerfile

      FROM scratch
      ADD alpine-minirootfs-3.10.0-x86_64.tar.gz /
      CMD ["/bin/sh"]
      

      由此可見,PHP鏡像是建立在debian這個鏡像的基礎上的,所以我們不需要像在虛擬機上面裝PHP一樣,得先用iso安裝一個Linux操作系統。

      項目位置在D:\www\php-cli-demo,建立好文件夾以后,在項目下面新建一個index.php文件:

      <?php
      echo phpversion();
      

      再新建一個Dockerfile文件:

      FROM php:7.2-cli
      WORKDIR /var/www/php-cli-demo
      COPY . .
      CMD ["php", "index.php"]
      

      WORKDIR是指定容器的工作目錄,我們需要把當前項目的代碼拷貝到容器的操作系統所在的目錄里,所以我們使用COPY,第一個點的意思是當前目錄,第二個點的意思是容器的當前目錄,意思就是把我win10系統下D:\www\php-cli-demo這個文件夾下的所有文件全部拷貝到容器的Debian系統下的當前目錄(已通過工作目錄指定為/var/www/php-cli-demo)下。

      CMD就是容器運行起來以后所要執行的命令了,這里我們希望直接運行這個php文件。

      在當前文件夾下,按住Shift鍵,然后按下鼠標右鍵,出現右鍵菜單,這時候出現其中一項“在此處打開Powershell窗口(s)”,這時候我們只需要按下s就可以進入命令行并且直接定位到當前文件夾了。

      然后我們根據剛才的Dockerfile配置文件來建立鏡像:

      docker build -t php-cli-demo .
      

      t是tag,打標簽的意思。

      最后那個點,指定了要打包的是哪個目錄,docker build 命令得知這個路徑后,會將路徑下的所有內容打包,然后上傳給 Docker 引擎。這樣 Docker 引擎收到這個上下文包后,展開就會獲得構建鏡像所需的一切文件,然后Docker引擎在解析上面的COPY指令時,就能知道要COPY哪些文件了,所以這個COPY的第一個參數的路徑是在打包路徑下展開的,是相對路徑。

      Docker默認會去找Dockerfile,也可以是別的文件名,例如你的Dockerfile叫build.conf,可以通過-f參數指定:

      docker build -t php-cli-demo -f build.conf .
      

      好了,鏡像構建成功了,現在馬上來跑一下吧:

      docker run --rm php-cli-demo
      

      可以看到正確輸出了PHP的版本號為:7.2.19。

      build的時候把項目代碼一塊打包進image鏡像文件了,那如果我要運行另外一個項目呢?要重新build一遍嗎?其實這個image是可以復用的,只不過在運行的時候指定項目位置就行了:

      docker run --rm -v ${PWD}:/var/www/php-cli-demo php-cli-demo
      

      v是volume,數據卷的意思,${PWD}是宿主機當前目錄,冒號后面是容器目錄,意思就是把當前目錄掛載到容器的/var/www/php-cli-demo目錄。

      不過不建議這么做,因為鏡像是一層一層做緩存的,所以重復build不會占用太多空間,而且如果鏡像做了改動,會影響到另外一個容器,所以還是單獨build比較好。感興趣的朋友可以自己做一下測試,然后用docker system df查看空間占用情況。

      如果像上面這種在基礎鏡像上,沒有涉及到任何加工的,只需要把項目映射到容器就行了,可以直接這么玩:

      docker run --rm -v ${PWD}:/var/www/demo -w /var/www/demo php:7.2-cli php index.php
      

      現在,回過頭來分析剛才的問題,為什么不建議在alpine容器里面直接安裝PHP。

      鏡像構建時,會一層一層地構建,前一層是后一層的基礎,這樣可以達到復用的效果。

      容器的實質是進程,但與直接在宿主執行的進程不同,容器進程運行于屬于自己的獨立的命名空間。因此容器可以擁有自己的 root 文件系統、自己的網絡配置、自己的進程空間,甚至自己的用戶 ID 空間。容器內的進程是運行在一個隔離的環境里,使用起來,就好像是在一個獨立于宿主的系統下操作一樣。這種特性使得容器封裝的應用比直接在宿主運行更加安全。

      鏡像使用的是分層存儲,容器也是如此。每一個容器運行時,是以鏡像為基礎層,在其上創建一個當前容器的存儲層。

      容器存儲層的生存周期和容器一樣,容器消亡時,容器存儲層也隨之消亡。因此,任何保存于容器存儲層的信息都會隨容器刪除而丟失。

      所以,你在alpine容器里面直接安裝PHP,如果不小心把容器刪掉了,下一次再跑的時候,PHP就丟了。而且這是一個黑箱操作,別人并不知道這個容器里面有什么,所以最好還是通過Dockerfile構建鏡像,然后再根據鏡像來跑容器咯。

      搭建LNMP

      好了,上面的都搞明白之后我們就來跑個真正的PHP項目吧。我們需要用到PHP-FPM,Nginx,MySQL。項目結構是這么安排的:

      • docker-php-demo
        • app
          • index.html
          • index.php
        • mysql
          • Dockerfile
        • nginx
          • conf.d
            • site.conf
        • php
          • Dockerfile

      我們先把Nginx裝起來,跑個靜態頁面試試。直接跑官方鏡像:

      docker run --name nginx -d --rm nginx:1.16
      

      打開瀏覽器輸入localhost,就可以看到Welcome to nginx!的靜態頁了。這是Nginx的默認頁面,我們需要加一個專門針對本次項目的配置。進入Nginx容器,查看配置文件路徑:

      docker exec -it nginx bash
      nginx -V
      

      看到配置文件路徑為:

      --conf-path=/etc/nginx/nginx.conf
      

      查看配置文件:

      cat /etc/nginx/nginx.conf
      

      可以看到默認的配置還會去加載其他配置文件:

      include /etc/nginx/conf.d/*.conf;
      

      所以我們只需要把項目的配置通過-v映射到容器的conf.d目錄下就可以了。把當前的Nginx容器停掉:

      docker stop nginx
      

      然后編寫site.conf:

      server {
          listen 80;
          server_name local.docker-php-demo.com;
          root /var/www/docker-php-demo;
      }
      

      在app目錄放入index.html:

      Hello Docker
      

      因為Nginx本身我們不做加工,所以不用Dockerfile,直接用官方鏡像就好了,然后分別把項目和Nginx網站配置都映射過去,在項目根目錄下執行:

      docker run --name dpd-nginx -d -v ${PWD}/app:/var/www/docker-php-demo -v ${PWD}/nginx/conf.d:/etc/nginx/conf.d -p 80:80 nginx:1.16
      

      最后在本機配置hosts就大功告成啦,Win + R 打開運行窗口,輸入drivers,打開etc/hosts文件加入一行域名配置:

      127.0.0.1 local.docker-php-demo.com
      

      瀏覽器打開local.docker-php-demo.com,到這里,我們就完成了讓Nginx跑靜態頁面的配置了。我們的項目是PHP,把fpm裝起來,然后再讓Nginx連上就行了,在php目錄下編寫Dockerfile:

      FROM php:7.2-fpm
      RUN cp /usr/local/etc/php/php.ini-development /usr/local/etc/php/php.ini \
          && docker-php-ext-install pdo_mysql
      

      上面我們使用了鏡像提供的安裝擴展的快捷操作方法來安裝pdo_mysql擴展。

      在app目錄放入index.php:

      <?php
      phpinfo();
      

      構建運行:

      cd php
      docker build -t dpd-php .
      cd ..
      docker run --name dpd-php -d -v ${PWD}/app:/var/www/docker-php-demo -p 9000:9000 dpd-php
      

      把php和nginx通過網卡連接起來:

      docker network create --driver bridge dpd # 新建一個橋接網卡,名字叫dpd
      docker network connect dpd dpd-php
      docker network connect dpd dpd-nginx
      docker network ls # 列出docker當前有哪些網卡
      docker network inspect dpd # 查看dpd網卡詳情
      

      修改Nginx配置,把PHP腳本轉發給fpm,fpm地址通過容器名dpd-php就可以識別:

      server {
          listen 80;
          server_name local.docker-php-demo.com;
          root /var/www/docker-php-demo;
          
          location ~ \.php$ {
              fastcgi_pass dpd-php:9000;
              include fastcgi_params;
              fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
          }
      }
      

      讓Nginx重新加載配置文件:

      docker exec -it dpd-nginx nginx -s reload
      

      到這里,我們就把Nginx 和 php-fpm搭起來了。下面我們再來搭建Mysql,在mysql目錄下新建test.sql,存放表結構和基礎數據:

      CREATE TABLE `user` (
          `id` int(10) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
          `name` varchar(20) NOT NULL
      )ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶';
      
      INSERT INTO `user` VALUES (null, 'a1');
      

      Dockerfile:

      FROM mysql:5.7
      ENV MYSQL_ROOT_PASSWORD=123 MYSQL_DATABASE=test
      COPY ./test.sql /var/data/test.sql
      

      構建并啟動容器,這里直接用--network參數把容器加入dpd網絡:

      cd mysql
      docker build -t dpd-mysql .
      docker run --name dpd-mysql -d --network dpd -p 3306:3306 dpd-mysql
      

      進入容器把表和測試數據導入進去:

      docker exec -it dpd-mysql bash
      mysql -uroot -p
      mysql> use test;
      mysql> source /var/data/test.sql
      

      修改index.php:

      <?php
      $dsn = 'mysql:dbname=test;host=dpd-mysql';
      $user = 'root';
      $password = '123';
      
      try {
          $dbh = new PDO($dsn, $user, $password);
          $sql = 'SELECT * FROM user WHERE id=?';
          $sth = $dbh->prepare($sql);
          $sth->execute(array(1));
          $result = $sth->fetch(PDO::FETCH_ASSOC);
          var_dump($result);
      } catch (PDOException $e) {
          echo 'Error: ' . $e->getMessage();
      }
      

      瀏覽器輸入http://local.docker-php-demo.com/index.php,PHP成功地從數據庫獲取到了用戶數據:

      array(2) { ["id"]=> string(1) "1" ["name"]=> string(2) "a1" }
      

      參考資料

      posted @ 2019-06-30 18:11  pigfly  閱讀(2689)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 日韩精品国内国产一区二| 亚洲精品国产无套在线观| 国内精品久久毛片一区二区| 国产在线午夜不卡精品影院| 国产精品亚洲а∨天堂2021| 亚洲午夜伦费影视在线观看| 性欧美VIDEOFREE高清大喷水| 人妻精品动漫H无码中字| 成人又黄又爽又色的视频| 精品少妇后入一区二区三区| 欧美 喷水 xxxx| 色悠久久网国产精品99| 最新精品露脸国产在线| 高潮喷水抽搐无码免费| 横山县| 偷拍视频一区二区三区四区| 国产精品自拍午夜福利| 国产国拍亚洲精品永久软件| 在线看av一区二区三区| 熟妇啊轻点灬大JI巴太粗| 国产免费网站看v片元遮挡| 成人午夜在线观看日韩| 日韩AV高清在线看片| 久久九九99这里有视频| 隔壁老王国产在线精品| 亚洲天堂一区二区三区三州| 国产精品有码在线观看| 狠狠色噜噜狠狠狠狠色综合久av| 亚洲成人免费一级av| 久久亚洲2019中文字幕| 东北女人毛多水多牲交视频| 亚洲女同精品中文字幕| 亚洲高清日韩专区精品| 激情亚洲内射一区二区三区| 99热国产这里只有精品9| 性男女做视频观看网站| 久久羞羞色院精品全部免费| 国产偷国产偷亚洲高清人| 四虎永久免费很黄的视频| 最新亚洲人成网站在线观看| 我要看亚洲黄色太黄一级黄|