摘要:傳送門加速目前國內比較多人用的加速器有和阿里云。啟動一條命令即可快速啟動一個服務器運行后,會自動從倉庫中下載最新的鏡像,并設置為密碼為,同時暴露出端口,容器命名為,并后臺運行。
docker 對于很多程序猿來說,一點都不陌生,畢竟它是一個輕量級的部署神器。
也許,也有很多童鞋和我一樣,只聽說過,卻沒有真正的實踐過 docker。那么,現在一起走進 docker 的世界。
什么是 Docker? Docker 概念Docker 和虛擬機(VM)的區別Docker is an open-source project that automates the deployment of applications inside software containers, by providing an additional layer of abstraction and automation of operating-system-level virtualization on Linux. Docker uses the resource isolation features of the Linux kernel such as cgroups and kernel namespaces, and a union-capable filesystem such as aufs and others to allow independent “containers” to run within a single Linux instance, avoiding the overhead of starting and maintaining virtual machines.
Docker是一個開放源代碼軟件項目,讓應用程序布署在軟件容器下的工作可以自動化進行,借此在Linux操作系統上,提供一個額外的軟件抽象層,以及操作系統層虛擬化的自動管理機制。Docker利用Linux核心中的資源分離機制,例如cgroups,以及Linux核心命名空間(name space),來建立獨立的軟件容器(containers)。這可以在單一Linux實體下運作,避免啟動一個虛擬機器造成的額外負擔。
——摘自維基百科
一張圖概括vm和docker的架構區別。具體的可以查看 知乎 - docker容器與虛擬機有什么區別?
總之明確一點, Docker 不是虛擬機。
Docker 的應用場景Web 應用的自動化打包和發布。
自動化測試和持續集成、發布。
在服務型環境中部署和調整數據庫或其他的后臺應用。
為什么要用 Docker? Docker 的優點Docker automates the repetitive tasks of setting up and configuring development environments so that developers can focus on what matters: building great software.
Docker自動執行設置和配置開發環境的重復任務,以便開發人員可以專注于重要的事情:構建出優秀的軟件。
Developers using Docker don’t have to install and configure complex databases nor worry about switching between incompatible language toolchain versions.
使用Docker的開發人員不必安裝和配置復雜的數據庫,也不用擔心在不兼容版本之間切換。
簡化配置
代碼流水線(Code Pipeline)管理
提高開發效率
隔離應用
整合服務器
調試能力Docker
多租戶環境
快速部署
獲取 Docker 安裝-- 來源于 DockOne.io - 八個Docker的真實應用場景
官方安裝。 傳送門
通過阿里云鏡像倉庫安裝
先登錄 阿里云 - 開發者平臺,登錄后進入管理中心,點擊管理中心中的 Docker Hub 鏡像站點。
通過 DaoCloud 安裝。 傳送門
Docker 加速目前國內比較多人用的加速器有 DaoCloud 和 阿里云。
阿里云
先登錄 阿里云 - 開發者平臺,登錄后進入管理中心,點擊管理中心中的 Docker Hub 鏡像站點。
可以看到控制臺中的專屬加速器。
DaoCloud
登錄后打開 [DaoCloud - 加速器](https://www.daocloud.io/mirror#accelerator-doc)即可看到配置 docker 加速器的腳本,拷貝代碼運行即可。非root用戶使用 docker
創建docker組: sudo groupadd docker
將當前用戶加入docker組: sudo gpasswd -a ${USER} docker
重新啟動docker服務:sudo systemctl restart docker
當前用戶退出系統重新登陸即可。
認識 Docker 查看Docker安裝情況Docker 安裝之后,可以使用 docker -v 查看docker 版本。
{17-09-19 10:59}Leung:~ lynnleung% docker -v Docker version 17.06.2-ce, build cec0b72
啟動第一個docker: hello-world 。
{17-09-19 11:00}Leung:~ lynnleung% docker run hello-world Unable to find image "hello-world:latest" locally latest: Pulling from library/hello-world 5b0f327be733: Pull complete Digest: sha256:1f19634d26995c320618d94e6f29c09c6589d5df3c063287a00e6de8458f8242 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://cloud.docker.com/ For more examples and ideas, visit: https://docs.docker.com/engine/userguide/Docker常用命令 pull
作用:從鏡像倉庫中拉取或者更新指定鏡像
語法: docker pull [OPTIONS] NAME[:TAG|@DIGEST]
options:
-a:拉取所有tagged鏡像
--disable-content-trust :忽略鏡像的校驗,默認開啟
TAG 默認為 latest,即拉取倉庫最新的鏡像。具體的tag值可以去官方hub中查看。
舉個栗子,拉取nginx鏡像,未指定tag時,默認拉取最新版本(在 Docker Hub - Nginx鏡像首頁可以看到,最新的nginx版本為 1.13.5):
{17-09-19 10:57}Leung:~ lynnleung% docker pull nginx Using default tag: latest latest: Pulling from library/nginx afeb2bfd31c0: Pull complete 7ff5d10493db: Pull complete d2562f1ae1d0: Pull complete Digest: sha256:aa1c5b5f864508ef5ad472c45c8d3b6ba34e5c0fb34aaea24acf4b0cee33187e Status: Downloaded newer image for nginx:latest
先把鏡像拉取下來,待會就可以直接使用。
run作用:創建一個新的容器,并運行一個命令
語法:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
常用的options:
-a stdin:指定標準輸入輸出內容類型,可選 STDIN/STDOUT/STDERR 三項
-d: 后臺運行容器,并返回容器ID
-i: 以交互模式運行容器,通常與 -t 同時使用
-t: 為容器重新分配一個偽輸入終端,通常與 -i 同時使用
--name="my-nginx": 為容器指定一個名稱
-h "hostname;": 指定容器的hostname
-e username="ritchie": 設置環境變量
--link=[]: 添加鏈接到另一個容器
--expose=[]: 開放一個端口或一組端口
-p hostport:containerport:指定容器暴露的端口對應宿主機的端口
-P:暴露容器端口對應宿主機的隨機端口
-v :給容器掛載存儲卷,掛載到容器的某個目錄
舉個栗子,運行一個nginx:
{17-09-19 11:32}Leung:~ lynnleung% docker run -P -d nginx 21ad408c79947d1cbee7540b1ae1586987acfc4bb6b09b6339b02879c70aeb2e {17-09-19 11:32}Leung:~ lynnleung% docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 21ad408c7994 nginx "nginx -g "daemon ..." 2 seconds ago Up 1 second 0.0.0.0:32768->80/tcp hopeful_clarke bd8dc013d734 hello-world "/hello" 31 minutes ago Exited (0) 31 minutes ago clever_bohr
可以看到 PORTS,容器中的 80 端口對應了宿主機中的 32768 端口,此時訪問 http://localhost:32768 即可看到nginx的默認頁面。
如果在虛擬機中運行 docker run -d -p 80:80 nginx 訪問虛擬機的地址 http://10.211.55.9,同樣可以打開nginx的默認頁面。
leung@ubuntu:~$ docker run -d -p 80:80 nginx 8b15325246d29c7b6f50cd3290c7a91fdf4b7d78240779720a2abdc64555ab45 leung@ubuntu:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8b15325246d2 nginx "nginx -g "daemon ..." 18 hours ago Up 18 hours 0.0.0.0:80->80/tcp flamboyant_mayerstart/stop/restart
作用:
docker start :啟動一個或多少已經被停止的容器
docker stop :停止一個運行中的容器
docker restart :重啟容器
語法:
docker start [OPTIONS] CONTAINER [CONTAINER...] docker stop [OPTIONS] CONTAINER [CONTAINER...] docker restart [OPTIONS] CONTAINER [CONTAINER...]
舉個栗子,停止虛擬機中的nginx:
leung@ubuntu:~$ docker stop flamboyant_mayer flamboyant_mayer leung@ubuntu:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8b15325246d2 nginx "nginx -g "daemon ..." 18 hours ago Exited (0) 3 seconds ago flamboyant_mayer
此時再訪問虛擬機ip已經是不能訪問了。
再運行 docker start flamboyant_mayer可以再次啟動nginx。
exec作用:在運行的容器中執行命令
語法:docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
options:
-d :分離模式: 在后臺運行
-i :即使沒有附加也保持STDIN 打開
-t :分配一個偽終端
舉個例子,進入虛擬機中的nginx容器查看nginx的版本和已安裝模塊:
leung@ubuntu:~$ docker exec -it flamboyant_mayer nginx -v nginx version: nginx/1.13.5 leung@ubuntu:~$ docker exec -i -t flamboyant_mayer /bin/bash root@8b15325246d2:/# nginx -V nginx version: nginx/1.13.5 built by gcc 6.3.0 20170516 (Debian 6.3.0-18) built with OpenSSL 1.1.0f 25 May 2017 TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt="-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.13.5/debian/debuild-base/nginx-1.13.5=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC" --with-ld-opt="-specs=/usr/share/dpkg/no-pie-link.specs -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie" root@8b15325246d2:/#
可以看到,最新版的nginx容器確實是 1.13.5 版本,并且安裝了大部分常用的模塊。
create作用: 創建一個新的容器但是不啟動它
語法: docker create [OPTIONS] IMAGE [COMMAND] [ARG...] 語法同 run
舉個栗子:
leung@ubuntu:~$ docker create -p 8888:80 --name create_nginx nginx ac3eca0321b872109b10444b4080b45f2b13333b8c265b4ec77fff05fc25ff61 leung@ubuntu:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ac3eca0321b8 nginx "nginx -g "daemon ..." 6 seconds ago Created create_nginx 8b15325246d2 nginx "nginx -g "daemon ..." 18 hours ago Up 10 minutes 0.0.0.0:80->80/tcp flamboyant_mayer leung@ubuntu:~$ docker start create_nginx create_nginx
運行 start 命令后,即可訪問虛擬機的 8888 端口。
build作用: 根據 Dockerfile 構建鏡像。
語法: docker build [OPTIONS] PATH | URL | -
常用的 options:
-f :指定要使用的Dockerfile路徑。
--force-rm :設置鏡像過程中刪除中間容器。
-q :安靜模式,成功后只輸出鏡像ID。
--no-cache :創建鏡像的過程不使用緩存。
--rm :設置鏡像成功后刪除中間容器。
ps作用: 列出容器
語法: create
options:
-a :顯示所有的容器,包括未運行的
-f :根據條件過濾顯示的內容
--format :指定返回值的模板文件
-l :顯示最近創建的容器
-n :列出最近創建的n個容器
--no-trunc :不截斷輸出
-q :靜默模式,只顯示容器編號
-s :顯示總的文件大小
leung@ubuntu:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8b15325246d2 nginx "nginx -g "daemon ..." 18 hours ago Up 8 minutes 0.0.0.0:80->80/tcp flamboyant_mayer leung@ubuntu:~$ docker ps -q 8b15325246d2 leung@ubuntu:~$ docker ps -s CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE 8b15325246d2 nginx "nginx -g "daemon ..." 18 hours ago Up 8 minutes 0.0.0.0:80->80/tcp flamboyant_mayer 16B (virtual 108MB) leung@ubuntu:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ac3eca0321b8 nginx "nginx -g "daemon ..." 6 seconds ago Created create_nginx 8b15325246d2 nginx "nginx -g "daemon ..." 18 hours ago Up 10 minutes 0.0.0.0:80->80/tcp flamboyant_mayerport
作用: 列出指定的容器的端口映射,或者查找將PRIVATE_PORT NAT到面向公眾的端口。
語法: docker port [OPTIONS] CONTAINER [PRIVATE_PORT[/PROTO]]
栗子:
leung@ubuntu:~$ docker port flamboyant_mayer 80/tcp -> 0.0.0.0:80top
作用: 查看容器中運行的進程信息,支持 ps 命令參數。
語法: docker top [OPTIONS] CONTAINER [ps OPTIONS]
栗子:
leung@ubuntu:~$ docker top flamboyant_mayer UID PID PPID C STIME TTY TIME CMD root 1999 1981 0 11:50 ? 00:00:00 nginx: master process nginx -g daemon off; systemd+ 2028 1999 0 11:50 ? 00:00:00 nginx: worker processimages
作用: 列出本地鏡像
語法: docker images [OPTIONS] [REPOSITORY[:TAG]]
常用的options:
-a :列出本地所有的鏡像(含中間映像層,默認情況下,過濾掉中間映像層)
-f :顯示滿足條件的鏡像
-q :只顯示鏡像ID
leung@ubuntu:~$ docker images -a REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 66216d141be6 10 days ago 108MBrm/rmi
用法: rm 用于刪除一個或多個容器,rmi 用于刪除一個或多個本地鏡像。
語法:
rm: docker rm [OPTIONS] CONTAINER [CONTAINER...]
rm 的options:
-f :通過SIGKILL信號強制刪除一個運行中的容器
-l :移除容器間的網絡連接,而非容器本身
-v:-v 刪除與容器關聯的卷
rmi: docker rmi [OPTIONS] IMAGE [IMAGE...]
rmi 的options:
-f :強制刪除
--no-prune :不移除該鏡像的過程鏡像,默認移除
tag作用: 標記本地鏡像,將其歸入某一倉庫。
語法: docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]
要注意這里的 username 指的是你注冊docker hub后,在hub上的唯一標識符,也是登錄的 username。
舉個栗子:docker tag nginx leungjz/nginx
push作用: 將本地的鏡像上傳到鏡像倉庫,要先登陸到鏡像倉庫
Linux登錄倉庫的方法是: 運行 docker login 命令,然后輸入dockerhub的登錄名和密碼即可,登錄名不是郵箱。
Mac 登錄倉庫為點擊狀態欄上的小鯨魚,在下拉欄中選擇 Sign in 登錄即可。
{17-09-19 14:28}Leung:~ lynnleung% docker login Login with your Docker ID to push and pull images from Docker Hub. If you don‘t have a Docker ID, head over to https://hub.docker.com to create one. Username: leungjz Password: Login Succeeded
語法: docker push [OPTIONS] NAME[:TAG]
options:
--disable-content-trust :忽略鏡像的校驗,默認開啟
在push前,需要標記本地某個鏡像,舉個栗子(Mounted 那里應為是基于我的測試賬號中tag過來。):
{17-09-19 14:32}Leung:~ lynnleung% docker tag nginx leungjz/nginx {17-09-19 14:33}Leung:~ lynnleung% docker push leungjz/nginx The push refers to a repository [docker.io/leungjz/nginx] 110566462efa: Mounted from buct132/nginx 305e2b6ef454: Mounted from buct132/nginx 24e065a5f328: Mounted from buct132/nginx latest: digest: sha256:d8565c25b654da69bc9b837a0dee713c988f0276e90564aa8fd12ebf4c2ff11e size: 948commit
作用: 從容器創建一個新鏡像。
語法: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
options:
-a :提交的鏡像作者
-c :使用Dockerfile指令來創建鏡像
-m :提交時的說明文字
-p :在commit時,將容器暫停
舉個栗子:
{17-09-19 14:48}Leung:~ lynnleung% docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6b06e2bb098e nginx "nginx -g "daemon ..." 38 minutes ago Up 38 minutes 10.211.55.2:80->80/tcp nginx {17-09-19 14:48}Leung:~ lynnleung% docker commit -a "leungjz" -m "my nginx" 6b06 leungjz/nginx sha256:3b4cb2b72b78be5da995e42ad051cbf0c73fd62fd437ac56469d8ee8f488b4c6 {17-09-19 14:49}Leung:~ lynnleung% docker images REPOSITORY TAG IMAGE ID CREATED SIZE leungjz/nginx latest 3b4cb2b72b78 6 seconds ago 108MB nginx latest da5939581ac8 5 days ago 108MB hello-world latest 05a3bd381fc2 6 days ago 1.84kB {17-09-19 14:49}Leung:~ lynnleung% docker push leungjz/nginx The push refers to a repository [docker.io/leungjz/nginx] a13795f76641: Pushed 110566462efa: Mounted from buct132/nginx 305e2b6ef454: Mounted from buct132/nginx 24e065a5f328: Layer already exists latest: digest: sha256:eaa0d73ad93f9ce2ebe8df0059d028742bcf1c92aeaebf65e9c2a9b3558f7acd size: 1155使用 Docker 搭建 lnmp 環境
既然 Docker 可以直接啟動 nginx 服務器,那么也肯定可以快速搭建 lnmp 環境。
為了方便管理,先新建一個項目目錄:
$ mkdir -p ./docker/mysql ./docker/php ./docker/nginx ./docker/php ./docker/project $ cd docker
其中,
mysql 目錄用于存放 mysql 的數據。
php 目錄用于存放 php.ini 配置文件
nginx 目錄用于存放 nginx 中的網站配置文件。
project 目錄用于存放項目文件。
啟動 MySql一條命令即可快速啟動一個mysql服務器:
docker run -p 3306:3306 -v $PWD/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d --name mysql mysql
運行后,docker 會自動從倉庫中下載最新的 mysql 鏡像,并設置為 root 密碼為 123456 ,同時暴露出 3306 端口,容器命名為 mysql,并后臺運行。
啟動 PHP-FPM這里的 php 使用 fpm 管理進程:
先新建一個 php.ini :
$ touch php/php.ini
配置文件中的配置項可以自行設置。
docker run -p 9000:9000 -v $PWD/project:/usr/share/nginx/html -v $PWD/php/php.ini:/usr/local/etc/php/conf.d/php.ini --link mysql:mysql -d --name php7-fpm php:7.1-fpm
從官方的 php7.1-fpm 為基礎容器。因為要連接數據庫,所以還得進入容器中安裝 php 的 pdo_mysql 模塊。
leung@ubuntu:~$ docker exec -i -t php7-fpm /bin/bash root@d254489bd9e4:/var/www/html# cd /usr/local/bin/ root@d254489bd9e4:/usr/local/bin# ./docker-php-ext-install pdo_mysql ...安裝過程省略... root@d254489bd9e4:/usr/local/bin# php -m ... PDO pdo_mysql pdo_sqlite ....
可以看到,已經安裝上了 pdo_mysql 的模塊。重啟 php 容器即可。
$ docker restart php7-fpm啟動 nginx
之前已經成功啟動nginx了,只需要在這基礎上,增加 php 文件的解析就可以了。
同理,先新建一個 nginx 配置文件: $ touch nginx/default.conf
其中,配置文件中需要將 php 文件轉發到 php-fpm 去處理即可,以前在宿主機中的配置一般都是轉發到 127.0.0.1:9000,但是現在容器的 ip 是不固定的,所以直接填 php7-fpm:9000,啟動容器時用 link 連接兩個容器,讓 docker 自動去識別容器的 ip 就可以了。當中的 php7-fpm 為 php-fpm 容器的名稱。 php 文件路徑要和 nginx 的文件路徑保持一致。
... # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ .php$ { # root html; fastcgi_pass php7-fpm:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name; include fastcgi_params; } ...
啟動 nginx :
docker run -p 80:80 -v $PWD/project:/usr/share/nginx/html -v $PWD/nginx/default.conf:/etc/nginx/conf.d/default.conf --link php7-fpm:php7-fpm -d --name nginx-fpm nginx
此時,一個簡易的 lnmp 環境已經搭好了,查看一下容器啟動情況:
leung@ubuntu:~/docker$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 490240532f1f nginx "nginx -g "daemon ..." About an hour ago Up About an hour 0.0.0.0:80->80/tcp nginx-fpm d254489bd9e4 php:7.1-fpm "docker-php-entryp..." About an hour ago Up 27 minutes 0.0.0.0:9000->9000/tcp php7-fpm 7f184683cc8d mysql "docker-entrypoint..." 2 hours ago Up 2 hours 0.0.0.0:3306->3306/tcp mysql測試訪問 php 文件
新建兩個測試文件: touch project/index.php project/i.php
index.php
"; try { $conn = new PDO("mysql:host=mysql;port=3306;dbname=mysql;charset=utf8", "root", "123456"); // 這里mysql 并不在同一個容器當中,所以連接數據庫時,只需要填寫 mysql 容器的名稱即可。 } catch (PDOException $e) { echo "Connection failed: " . $e->getMessage(); } $conn->exec("set names utf8"); $sql = "SELECT * FROM `user` WHERE 1"; $result = $conn->query($sql); while($rows = $result->fetch(PDO::FETCH_ASSOC)) { echo $rows["Host"] . " " . $rows["User"]."
"; } ?>
i.php
打開瀏覽器訪問 http://10.211.55.9/i.php:
雖然我們確實能快速搭建了一個 lnmp 的環境,但是每次切換宿主機時,都要執行多個步驟:
啟動 mysql 服務器
啟動 php 服務器
進入 php 容器修改配置
啟動 nginx 服務器
怎么說都還是麻煩。如果能一鍵啟動的話,那就更好了。
Dockerfile 就可以解決這樣的問題。
要使用 Dockerfile ,先要了解一下這到底是個什么東西。
什么是 Dockerfile?Dockerfile 常用命令 FROMA Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build users can create an automated build that executes several command-line instructions in succession.
Dockerfile是一個文本文檔,其中包含用戶可以在命令行上調用以組合鏡像的所有命令。使用docker構建用戶可以創建一個自動構建,連續執行幾個命令行指令。
語法: FROM
注意:FROM 命令必須是 Dockerfile 的首個命令,但可以在一個 Dockerfile 中出現多次。
說明: 該命令定義了使用哪個基礎鏡像啟動構建流程?;A鏡像可以為任意鏡像。
MAINTAINER語法: MAINTAINER
說明: 設置生成鏡像的作者名字。
RUN語法:
RUN
RUN ["
說明:
RUN命令將在當前image中執行任意合法命令并提交執行結果。
RUN 指令緩存不會在下個命令執行時自動失效。
RUN命令用于創建鏡像(在之前commit的層之上形成新的層)。
ADD語法:
ADD
ADD ["
注意:ADD只有在build鏡像的時候運行一次,后面運行container的時候不會再重新加載了。
說明: 從 src 拷貝新的文件或文件夾或遠程文件 URL 到鏡像的文件系統的路徑 dest 中。
所有拷貝到 container 中的文件和文件夾權限為 0755 , uid 和 gid 為0。
如果文件是可識別的壓縮格式,則 docker 會自動解壓縮。
如果 src 為本地文件或文件夾,則必須相對于 docker build
dest 是一個絕對路徑,或者相對于 WORKDIR ,如果
COPY
COPY ["
COPY 的語法和使用說明和 ADD 基本一致,但是在遇見壓縮包時, COPY 很直接的拷貝到容器當中,而不會解壓。 Docker 團隊建議大多數情況下使用 COPY。
CMD語法:
CMD ["
CMD ["
CMD
注意:Dockerfile 中只能有一個 CMD 指令,如果有多個則只有最后一個生效。
說明:
CMD 命令最主要的目的是提供一個默認的執行容器。
和RUN命令相似,CMD可以用于執行特定的命令。和RUN不同的是,這些命令不是在鏡像構建的過程中執行的,而是在用鏡像構建容器后被調用。
如果 CMD 用于為 ENTRYPOINT 提供默認參數時, CMD 和 ENTRYPOINT 指令應該規定為 JSON 數組格式。
當 docker run command 的命令匹配到 CMD command 時,會替換CMD執行的命令,即 docker run命令如果指定了參數會把CMD里的參數覆蓋: (這里說明一下,如:docker run -it ubuntu /bin/bash 命令的參數是指/bin/bash 而非 -it ,-it只是docker 的參數,而不是容器的參數,以下所說參數均如此。)
ENTERYPOINT語法:
ENTRYPOINT ["
ENTRYPOINT
注意:Dockerfile 中只能有一個 ENTRYPOINT 指令,如果有多個則只有最后一個生效。
說明:
配置容器啟動后執行的命令,并且參數不可被 docker run 提供的參數覆蓋。
如果結合 CMD 使用時,要使用 exec 的形式,即:
ENTRYPOINT ["echo"] CMD ["HELLO_WORLD"]
這是 CMD 命令的內容則不是一個完整的指令,而是為 ENTRYPOINT 命令提供默認參數,該參數可以被 docker run 后的參數所覆蓋。
EXPOSE語法: EXPOSE
說明: 通知 Docker 在運行時監聽指定的端口。主機上要用還得在啟動container時,做host-container的端口映射。
ENV語法:
ENV
ENV
說明:
該指令將環境變量的 key 設置為 value ,這些值都可以在 Dockerfile 后續的命令中用上,并可以被修改。
VOLUME語法:
VOLUME ["
VOLUME
說明: 創建一個有具體名稱的掛載點,并將其標記為從本機或者其他容器外部的掛載卷。
USER語法: USER
說明: 指定某個用戶運行容器。
WORKDIR語法: WORKDIR
說明: 設定指令 CMD , RUN , ENTRYPOINT , COPY 和 ADD 的工作目錄??梢栽谝粋€ Dockerfile 中出現多次,如果提供了一個相對路徑,那么它將相對于前一個 WORKDIR 指令的路徑。
ARG語法: ARG
說明:
定義一個變量,用戶可以在建立的時候通過 docker build 命令使用 —build-arg
多條 ARG 指令可以定義指定的變量,但是在構建成功后取消。
相同名字的環境變量會被 ENV 指令的覆蓋。
Docker 有一組預定義的 ARG 變量,可以在 Dockerfile 中使用而不需要 ARG 指令。
ONBUILD語法: ONBUILD
說明:
當鏡像作為另一個鏡像構建的基礎時,添加一個被延時執行的觸發指令。就類似于在子鏡像的 Dockerfile 的 FROM 指令下插入了一條命令。
ONBUILD 指定的命令在構建鏡像時不執行,只在它的子鏡像中執行。
任何構建指令都可以被注冊為觸發器,但 ONBUILD 指令不一定觸發 FROM , MAINTAINER 或者 ONBUILD 指令。
Dockerfile 構建鏡像現在將先前搭建 lnmp 的具體步驟一步步寫進 Dockerfile 中。
MySQLFROM mysql MAINTAINER LeungJZ ENV MYSQL_ROOT_PASSWORD 123456 EXPOSE 3306
沒啥太多的配置,就是簡單的配置ROOT密碼和暴露3306端口。
構建鏡像:
leung@ubuntu:~/docker$ docker build ./mysql/ -t test-mysql Sending build context to Docker daemon 2.56kB Step 1/4 : FROM mysql ---> 141d24fea983 Step 2/4 : MAINTAINER LeungJZ ---> Using cache ---> aa6665261e02 Step 3/4 : ENV MYSQL_ROOT_PASSWORD 123456 ---> Using cache ---> 4d482f48a09d Step 4/4 : EXPOSE 3306 ---> Using cache ---> 385bb10cd49a Successfully built 385bb10cd49a Successfully tagged test-mysql:latest
瞬間構建成功。再啟動一個容器 docker run --name mysql -p 3306:3306 -d test-mysql ,和以前基本一致。
Php7.1-fpmFROM php:7.1-fpm MAINTAINER LeungJZ COPY php.ini /usr/local/etc/php/conf.d/php.ini RUN /usr/local/bin/docker-php-ext-install pdo_mysql EXPOSE 9000 CMD ["php-fpm"]
指定了 php-fpm 的版本為 7.1,并覆蓋了我們自定義的 php.ini ,并且安裝 pdo_mysql 拓展。
leung@ubuntu:~/docker$ docker build ./php/ -t test-php7 Sending build context to Docker daemon 70.14kB Step 1/6 : FROM php:7.1-fpm ---> 9b44e8b4c8b6 Step 2/6 : MAINTAINER LeungJZ ---> Using cache ---> 1038ce686af9 Step 3/6 : COPY php.ini /usr/local/etc/php/conf.d/php.ini ---> Using cache ---> cdbdece75628 Step 4/6 : RUN /usr/local/bin/docker-php-ext-install pdo_mysql ---> Using cache ---> 8a8cbd9c8ac9 Step 5/6 : EXPOSE 9000 ---> Using cache ---> 1fd3881b6769 Step 6/6 : CMD php-fpm ---> Using cache ---> 00d178a9351b Successfully built 00d178a9351b Successfully tagged test-php7:latest
因為之前構建過一次,所以全都是從緩存中獲取,直接就構建完成。
啟動: docker run --name php7-fpm --link mysql:mysql -p 9000:9000 -v $PWD/project:/usr/share/nginx/html -d test-php7 。
nginxFROM nginx:1.13 MAINTAINER LeungJZ COPY default.conf /etc/nginx/conf.d/default.conf EXPOSE 80 ENTRYPOINT ["nginx", "-g", "daemon off;"]
配置就是基礎鏡像為 1.13 版本的 nginx ,覆蓋自定義的 default.conf 配置文件,暴露80端口,并且不以守護進程模式啟動。
leung@ubuntu:~/docker$ docker build ./nginx/ -t test-nginx Sending build context to Docker daemon 4.608kB Step 1/5 : FROM nginx:1.13 ---> da5939581ac8 Step 2/5 : MAINTAINER LeungJZ ---> Using cache ---> 3076338acc32 Step 3/5 : COPY default.conf /etc/nginx/conf.d/default.conf ---> Using cache ---> bb7ab780e5d4 Step 4/5 : EXPOSE 80 ---> Using cache ---> 38dda9a94ae6 Step 5/5 : ENTRYPOINT nginx -g daemon off; ---> Using cache ---> 7864bf277ac0 Successfully built 7864bf277ac0 Successfully tagged test-nginx:latest
啟動: docker run --name nginx --link php7-fpm:php7-fpm -v $PWD/project:/usr/share/nginx/html -p 80:80 -d test-nginx 。
訪問 http://10.211.55.9/i.php 依舊可以看到熟悉的 phpinfo 的界面。
小結Dockerfile 可以幫我們減輕了很多配置方面的麻煩,但是啟動時,依舊需要綁定很多變量,如掛載卷,映射端口等。雖然只需 run 一次,但是這也是麻煩的。
當然,肯定有解決的辦法,就是接下來的 docker-compose 。
docker-composeCompose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration.
Docker-compose 是一個定義和運行多容器 Docker 程序的工具。在 compose 中,可以用 YAML 文件來配置程序的服務,然后使用簡單的命令即可從配置中創建并啟動所有服務。
一個使用Docker容器的應用,通常由多個容器組成。使用Docker Compose,不再需要使用 shell 腳本來啟動容器。在配置文件中,所有的容器通過 services 來定義,然后使用 docker-compose 腳本來啟動,停止和重啟應用,和應用中的服務以及所有依賴服務的容器。
安裝 composeLinux:
# 下載最新的 docker-compose sudo curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose # 給予下載的 docker-compose 執行權限 sudo chmod +x /usr/local/bin/docker-compose # 測試是否可用 docker-compose --version docker-compose version 1.15.0, build e12f3b9
其他操作系統可以 查看這里 。
配置 docker-compose.yml整個配置文件應該包含 version 、services 、 networks 三大部分,其中最關鍵是 services 和 networks 兩部分。
version下表顯示了 compose 文件版本支持特定的 docker 版本。
Compose file format | Docker Engine release |
---|---|
3.3 | 17.06.0+ |
3.2 | 17.04.0+ |
3.1 | 1.13.1+ |
3.0 | 1.13.0+ |
2.3 | 17.06.0+ |
2.2 | 1.13.0+ |
2.1 | 1.12.0+ |
2.0 | 1.10.0+ |
1.0 | 1.9.1.+ |
在 services 標簽下的標簽是指該服務的名稱,為用戶自定義。
image
指定服務的鏡像名稱或者鏡像ID ,若本地不存在,則 compose 將會嘗試拉取該鏡像。 用法:
image: ubuntu image: nginx:1.13 image: containerID
?
build
服務即可基于某個鏡像 image ,亦可基于一個 Dockerfile 文件。在使用命令 `docker-compose up` 構建任務時,將會自動用 build 指向的 Dockerfile 路徑構建鏡像,并使用該鏡像啟動服務容器。 **如果同時指定了 image 和 build,那么 compose 會將 build 出來的鏡像命名為 image。** 用法:
build: ./nginx # 設定上下文目錄 build: context: ./ Dockerfile: nginx/Dockerfile
args
和 Dockerfile 中的 ARG 用法一樣,在構建中指定環境變量,構建完成后取消。 args 中的變量可以為空值。 **注意:如需要在 yaml 中使用布爾值(true,false, yes,no等)必須要用引號括起來。** 用法:
args: - version=1.0 - boolean="true" - emptyvar
command
可以覆蓋啟動容器后默認執行的命令。 用法:
command: nginx command: [nginx, -g, deamon off]
container_name
設置容器的名稱,默認為:用法:
container_name: lnmp_nginx
depends_on
設置依賴。有時候某個容器需要另外一個容器作為依賴,則該命令可以解決依賴前后問題。如啟動 nginx 前要先啟動 php-fpm,這時候只需要這么寫:
depends_on: - php-fpm
entrypoint
用法和 Dockerfile 中的ENTRYPOINT 一致,會覆蓋 Dockerfile 中的 ENTRYPOINT。
environment
設置鏡像中的環境變量,可以被保存在鏡像當中,即每次啟動容器,這些變量依舊存在容器當中。寫法和 args 一致:
environment: - MYSQL_ROOT_PASSWORD: 123456
expose
暴露容器中的端口,和 Dockerfile 中的EXPOSE 用法一致。
links
類似于 `docker run` 中的 `—link` 參數,用于連接容器。如 nginx 容器需要連接 php-fpm 的容器,只需要這么寫:
links: - php7-fpm:php
其中,php 為 nginx 容器中連接 php 的別名,php7-fpm 為 php-fpm 服務的名字。
ports
用于映射端口,用法和 `docker run` 的參數 `-p` 一致:
ports: - "8888:80"
將容器的 80 端口映射到宿主機的 8888 端口中。
volumes
掛載一個目錄或者一個數據卷容器到 container 中。數據卷的路徑可以是絕對的,相對的。 用法: `[HOST:CONTAINER]` or `[HOST:CONTAINER:rw]` rw的意思是,容器對該卷可讀可寫;ro為只讀。
volumes: # 只在容器中創建一個數據卷 - /website/html # 絕對路徑 - /home/website:/website/html # 相對路徑 - ./data:/website/html # 已存在的數據卷容器,并設置權限為只讀 - data_container:/website/html:ro
?
volumes_from
從其他容器或者服務掛載數據卷,可選參數為 `:ro` 只讀 或者 `:rw` 可讀可寫。默認為可讀可寫。
networks
指定容器加入的網絡:
services: nginx: networks: web_app
web_app 為網絡名稱。
還有其他的配置項,具體的可以去 官網查看 。
編寫一個多容器配置先創建如下目錄:
./ ├── conf // 配置文件目錄 │?? ├── mysql │?? ├── nginx │?? └── php ├── data // mysql 數據目錄 ├── logs // 日志文件目錄 │?? ├── mysql │?? ├── nginx │?? └── php └── www // 項目目錄
新建一個 docker-compose.yml 文件:
version: "2" services: nginx: image: nginx:1.13 ports: - "80:80" volumes: - ./www:/usr/share/nginx/html:rw - ./logs/nginx/:/var/log/nginx:rw - ./conf/nginx/conf.d:/etc/nginx/conf.d:ro links: - php:fpm depends_on: - php php: build: ./conf/php ports: - "9000:9000" volumes: - ./www:/usr/share/nginx/html:rw - ./logs/php/:/var/log/php:rw links: - mysql:mysql depends_on: - mysql mysql: image: mysql:5 ports: - "3306:3306" volumes: - ./mysql:/var/lib/mysql:rw environment: MYSQL_ROOT_PASSWORD: "123456" MYSQL_USER: "test" MYSQL_PASSWORD: "testpass"
version 為2 可以兼容舊版本的docker。
services 這里一共啟動了3個服務:
nginx。監聽 80 端口,掛載了 www 目錄為工作目錄,掛載 logs/nginx 為日志目錄,掛載 conf/nginx/conf.d 至容器的 nginx 的配置文件夾。連接 php 容器,表示為 fpm。依賴于 php 容器。
php。 監聽 9000 端口,掛載 www 目錄為工作目錄,掛載 logs/php 為日志目錄,依賴于 mysql 容器并連接 mysql 容器。
mysql。監聽 3306 端口,掛載 mysql 目錄為 mysql 數據存儲目錄,并設置了3個環境變量,分別為 root密碼,mysql 用戶 test 并設置 test 的密碼為 testpass。
配置文件自行添加,最終的目錄結構為:
. ├── conf │?? ├── mysql │?? ├── nginx │?? │?? └── conf.d │?? │?? ├── default.conf │?? │?? └── home.conf │?? └── php │?? ├── Dockerfile │?? └── php.ini ├── docker-compose.yml ├── logs │?? ├── mysql │?? ├── nginx │?? └── php ├── mysql └── www ├── home │?? └── index.html ├── index.html ├── index.php └── i.php
因為 php-fpm 我們需要做額外的事情,所以使用 Dockerfile 來構建鏡像。php 的 Dockerfile 的內容配置和之前的 Dockerfile 一致:
FROM php:7.1-fpm MAINTAINER LeungJZ COPY php.ini /usr/local/etc/php/conf.d/php.ini RUN docker-php-ext-install pdo_mysql EXPOSE 9000 CMD ["php-fpm"]
可以在 RUN 命令中,安裝需要的 php 拓展。
在項目根目錄中運行命令 docker-compose up 開始構建。
leung@ubuntu:~/compose$ docker-compose up Pulling mysql (mysql:5)... 5: Pulling from library/mysql aa18ad1a0d33: Already exists fdb8d83dece3: Pull complete 75b6ce7b50d3: Pull complete ed1d0a3a64e4: Pull complete 8eb36a82c85b: Pull complete 41be6f1a1c40: Pull complete 0e1b414eac71: Pull complete 914c28654a91: Pull complete 587693eb988c: Pull complete b183c3585729: Pull complete 315e21657aa4: Pull complete Digest: sha256:0dc3dacb751ef46a6647234abdec2d47400f0dfbe77ab490b02bffdae57846ed Status: Downloaded newer image for mysql:5 Building php Step 1/6 : FROM php:7.1-fpm ---> 9b44e8b4c8b6 Step 2/6 : MAINTAINER LeungJZ ---> Running in e5c103cc2d37 ---> c396815cf8b6 Removing intermediate container e5c103cc2d37 Step 3/6 : COPY php.ini /usr/local/etc/php/conf.d/php.ini ---> bc4a19e69f93 Removing intermediate container 566b27944ffb Step 4/6 : RUN /usr/local/bin/docker-php-ext-install pdo_mysql ---> Running in 8ebd9dadf506 ---> a3483051c1bb Removing intermediate container 8ebd9dadf506 Step 5/6 : EXPOSE 9000 ---> Running in 9a4f81103c0c ---> d0376a2a8bfe Removing intermediate container 9a4f81103c0c Step 6/6 : CMD php-fpm ---> Running in 8d7f61c657f9 ---> 77072c6b2561 Removing intermediate container 8d7f61c657f9 Successfully built 77072c6b2561 Successfully tagged compose_php:latest WARNING: Image for service php was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`. Creating compose_mysql_1 ... Creating compose_mysql_1 ... done Creating compose_php_1 ... Creating compose_php_1 ... done Creating compose_nginx_1 ... Creating compose_nginx_1 ... done Attaching to compose_mysql_1, compose_php_1, compose_nginx_1
不出1分鐘,整個項目環境就已經搭建好了。根據提醒, php 服務已經被構建出來了,因為它一開始并不存在。如果想要重新構建整個服務,需要運行 docker-compose build or docker-compose up --build 。
這時 docker ps 查看:
leung@ubuntu:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 18bc61bd12b1 nginx:1.13 "nginx -g "daemon ..." About a minute ago Up About a minute 0.0.0.0:80->80/tcp compose_nginx_1 38ccb807e09b compose_php "docker-php-entryp..." About a minute ago Up About a minute 0.0.0.0:9000->9000/tcp compose_php_1 67188d651b80 mysql:5 "docker-entrypoint..." About a minute ago Up About a minute 0.0.0.0:3306->3306/tcp compose_mysql_1
可以看到已經成功啟動了三個容器。
通過瀏覽器訪問:
可以發現已經運行成功,而且 php 文件也能正常執行。
docker-compose 命令和 docker 差不多,也有 start , stop, build , logs , rm 等常用命令,其作用也是類似的。
總結docker 真是一個神器!??!
這只是一個簡單的入門,希望大家能繼續挖掘 docker 更強大的功能。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/25913.html
摘要:瀏覽器緩存的分類瀏覽器緩存主要有兩類緩存協商和徹底緩存,也有稱之為協商緩存和強緩存。只能被終端用戶的瀏覽器緩存,不允許等中繼緩存服務器對其緩存。 今天小微開店寶在測試環境發布更新的時候,同事問:為什么我需要手動清理瀏覽器緩存才能看到變更?難道系統上線后也需要客戶自己清理瀏覽器緩存嗎!看來,這個坑需要我來填了。 什么是瀏覽器緩存 瀏覽器緩存(Brower Caching)是瀏覽器在本地磁...
摘要:傳送門加速目前國內比較多人用的加速器有和阿里云。啟動一條命令即可快速啟動一個服務器運行后,會自動從倉庫中下載最新的鏡像,并設置為密碼為,同時暴露出端口,容器命名為,并后臺運行。 docker 對于很多程序猿來說,一點都不陌生,畢竟它是一個輕量級的部署神器。 也許,也有很多童鞋和我一樣,只聽說過,卻沒有真正的實踐過 docker。那么,現在一起走進 docker 的世界。 什么是 Doc...
摘要:構造函數也是函數,所以當你用普通調用方式調用時這個時候相當于給對象添加了和兩個屬性。為構造函數指定這里報錯了,原因是我們去了函數,這里的函數不是一個構造函數當然解決方式也是有的。 前言 javascript中的this是啥東西?為啥我們經常被他搞得暈頭轉向不知所以?他是惡魔?是天使 ?是怪胎?讓我們一起來揭開它那神秘的面紗。 showImg(https://segmentfault.c...
摘要:詞云可以通過網站紐扣詞云來制作,然而可以通過代碼來實現,下面開始吧。 詞云可以通過網站 https://wordart.com/ 紐扣詞云http://cloud.niucodata.com/ 來制作,然而 Python 可以通過代碼來實現,下面開始吧。 showImg(https://segmentfault.com/img/bVQzIx?w=874&h=416); pip inst...
閱讀 2742·2021-11-24 10:23
閱讀 1153·2021-11-17 09:33
閱讀 2503·2021-09-28 09:41
閱讀 1409·2021-09-22 15:55
閱讀 3641·2019-08-29 16:32
閱讀 1903·2019-08-29 16:25
閱讀 1056·2019-08-29 11:06
閱讀 3421·2019-08-29 10:55