1. Mở đầu
Xin chào các bạn, sau khi đi qua hai phần đầu của series:
8, chúng ta đã tìm hiểu//hub.docker.com/_/mysql/
9 là gì và sử dụng chúng như thế nào.//hub.docker.com/_/mysql/
Hôm nay chúng ta sẽ tiếp tục tìm hiểu
0 - một công cụversion: '3.5'
1 cácversion: '3.5'
2 lại và làm cho chúng có thểversion: '3.5'
3 với nhau.version: '3.5'
2. Bài toán
Câu chuyện đặt ra là:
version: '3.5'
4Dự án
5version: '3.5'
Hoặc dự án
6version: '3.5'
version: '3.5'
7Qua tìm hiểu ở hai phần đầu của series, chúng ta hoàn toàn có thể sử dụng
8version: '3.5'
Cài đặt tất cả những môi trường cần thiết [như mysql, redis, php,... ] lên một container
9version: '3.5'
Rồi chạy project trên container đó.
services:
mysql:
...
...
...
app:
...
...
...
0Nếu như bạn muốn dùng kết hợp nhiều
1 trên DockerHub thì sao ?services: mysql: ... ... ... app: ... ... ...
Nếu một cơ sở dữ liệu
2 cho nhiều project thì sẽ xử lý thế nào ?services: mysql: ... ... ... app: ... ... ...
Hơn nữa, với tư duy của OOP, 1 class thì không nên
3.services: mysql: ... ... ... app: ... ... ...
services:
mysql:
...
...
...
app:
...
...
...
4- Khi đó, chúng ta sẽ xây dựng nhiều container, khi nào cần tương tác với database thì gọi tới
5 chẳng hạn, tương tác với redis thì gọi tớiservices: mysql: ... ... ... app: ... ... ...
6, cần cái gì thì gọi tới container làm nhiệm vụ đó.services: mysql: ... ... ... app: ... ... ...
- Cùng nhìn hình ảnh con
7 đại diện choservices: mysql: ... ... ... app: ... ... ...
0 [mình đoán thế] đang dùng các xúc tu để cuộn các container lên kìa.version: '3.5'
services:
mysql:
...
...
...
app:
...
...
...
9À quên, bài viết sử dụng Rails framework [một framework của Ruby dùng để lập trình web] để ứng dụng Docker, còn với các framework của
0 haymysql: image: mysql:5.7 container_name: mysql restart: always environment: MYSQL_ROOT_PASSWORD: root volumes: - docker/database:/var/lib/mysql
1 thì mình sẽ tìm cách làm tương tự nha.mysql: image: mysql:5.7 container_name: mysql restart: always environment: MYSQL_ROOT_PASSWORD: root volumes: - docker/database:/var/lib/mysql
Quan trọng là mình hiểu cách sử dụng
0, nếu có điều kiện, mình sẽ tìm hiểu và viết thêm bài hướng dẫn sử dụng Docker trên Laravel hoặc các framework khác.version: '3.5'
Các bạn cũng có thể skip để chuyển sang Docker: Chưa biết gì đến biết dùng [ Phần 4 - Một số trick tối ưu và lưu ý ]
mysql:
image: mysql:5.7
container_name: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- docker/database:/var/lib/mysql
3 3. Cài đặt Docker-compose
Tham khảo trên trang chủ nào, trên
mysql:
image: mysql:5.7
container_name: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- docker/database:/var/lib/mysql
4 thì sẽ như sau:
5 Run this command to download the latest version of Docker Compose.mysql: image: mysql:5.7 container_name: mysql restart: always environment: MYSQL_ROOT_PASSWORD: root volumes: - docker/database:/var/lib/mysql
sudo curl -L "//github.com/docker/compose/releases/download/1.22.0/docker-compose-$[uname -s]-$[uname -m]" -o /usr/local/bin/docker-compose
6 Apply executable permissions to the binarymysql: image: mysql:5.7 container_name: mysql restart: always environment: MYSQL_ROOT_PASSWORD: root volumes: - docker/database:/var/lib/mysql
sudo chmod +x /usr/local/bin/docker-compose
7 Test the installationmysql: image: mysql:5.7 container_name: mysql restart: always environment: MYSQL_ROOT_PASSWORD: root volumes: - docker/database:/var/lib/mysql
docker-compose --version
-> Đây là phiên bản đang cài đặt trên máy tính của mình:
docker-compose version 1.23.1, build b02f1306
mysql:
image: mysql:5.7
container_name: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- docker/database:/var/lib/mysql
8 4. Cấu trúc thư mục
mysql:
image: mysql:5.7
container_name: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- docker/database:/var/lib/mysql
9Khá là hay ho khi trên trang chủ Docker đã có bài hướng dẫn Docker for Rails.
Thông thường, mình thấy tham khảo trên trang chủ cũng khá là đủ rồi
Nhưng cũng hơi bất ngờ khi trong thực tế làm dự án, anh em trong team nhận thấy vẫn còn một số điểm
0# Ignore data backup docker/database
Nên sau đây chúng ta cùng tìm hiểu cách
1 dựa vào bài hướng dẫn trên và đống thời# Ignore data backup docker/database
2 hơn nhé ! Nếu các bạn nhận thấy phần nào có thể làm tốt hơn thì mời comment bên dưới nha.# Ignore data backup docker/database
# Ignore data backup
docker/database
3Bao gồm 3 file sau:
4:# Ignore data backup docker/database
Liệt kê những câu lệnh cần chạy sau khi bật container.
5# Ignore data backup docker/database
Về công dụng của nó thì chắc hẳn các bạn còn nhớ chúng ta đã đề cập ở bài trước:
6:# Ignore data backup docker/database
Dùng để
7 và# Ignore data backup docker/database
8 hoạt động của các# Ignore data backup docker/database
2 trong project.version: '3.5'
5. Xác định các container cần thiết
Ở mức cơ bản nhất, chúng ta sẽ xây dựng 2 container:
app:
container_name: app
build: .
volumes:
- .:/my_app
ports:
- "3000:3000"
environment:
DATABASE_HOST: mysql
DATABASE_USER_NAME: root
DATABASE_PASSWORD: root
0Hiện nay, phần lớn các dự án có lẽ hay sử dụng
1, để gần gũi và quen thuộc với mọi người nên mình sẽ dùng cơ sở dữ liệu mysql.app: container_name: app build: . volumes: - .:/my_app ports: - "3000:3000" environment: DATABASE_HOST: mysql DATABASE_USER_NAME: root DATABASE_PASSWORD: root
Còn nếu hịn hò hơn thì bạn có thể tìm hiểu và sử dụng
2 nhéapp: container_name: app build: . volumes: - .:/my_app ports: - "3000:3000" environment: DATABASE_HOST: mysql DATABASE_USER_NAME: root DATABASE_PASSWORD: root
Teachnical leader của dự án mình cũng khuyến khích sài công cụ này, và google một hồi thì có vẻ như nó có nhiều ưu điểm hơn thật, ví dụ như lưu trữ với kiểu dữ liệu array hay gán giá trị mặc định với kiểu dữ liệu
3 ...app: container_name: app build: . volumes: - .:/my_app ports: - "3000:3000" environment: DATABASE_HOST: mysql DATABASE_USER_NAME: root DATABASE_PASSWORD: root
Quay trở lại vấn đề chính nào, quan sát:
//hub.docker.com/_/mysql/
Chúng ta sẽ thấy tên organization là
4 và bên dưới tên image có dòng chữapp: container_name: app build: . volumes: - .:/my_app ports: - "3000:3000" environment: DATABASE_HOST: mysql DATABASE_USER_NAME: root DATABASE_PASSWORD: root
5app: container_name: app build: . volumes: - .:/my_app ports: - "3000:3000" environment: DATABASE_HOST: mysql DATABASE_USER_NAME: root DATABASE_PASSWORD: root
Đây chính là những
6 được Docker cung cấp, chúng ta sẽ yên tâm hơn khi sử dụng, và khuyến cáo luôn là nên sử dụng [Hàng chính hãng, ít có khả năng gặp bug hơn hoặc chèn mã độc]app: container_name: app build: . volumes: - .:/my_app ports: - "3000:3000" environment: DATABASE_HOST: mysql DATABASE_USER_NAME: root DATABASE_PASSWORD: root
Trên DockerHub còn rất nhiều image khác dành cho mysql, ví dụ bitnami/mysql
Đây là những image do các cá nhân, tổ chức khác xây dựng, có thể sẽ có những cải tiến so với bản official nhưng độ tin cậy và chính xác thì khó mà bằng bản chuẩn được.
app:
container_name: app
build: .
volumes:
- .:/my_app
ports:
- "3000:3000"
environment:
DATABASE_HOST: mysql
DATABASE_USER_NAME: root
DATABASE_PASSWORD: root
7Có thể có bạn chưa rõ, ta có PHP là một ngôn ngữ lập trình, Laravel là một PHP framework, dùng để lập trình web.
Thì tương tự như vậy, Ruby cũng là một ngôn ngữ lập trình, Rails là một Ruby framework dùng để lập trình web.
Lát nữa chúng ta dùng image ruby này để tạo
2 choversion: '3.5'
9 nhé !app: container_name: app build: . volumes: - .:/my_app ports: - "3000:3000" environment: DATABASE_HOST: mysql DATABASE_USER_NAME: root DATABASE_PASSWORD: root
sudo chmod +x /usr/local/bin/docker-compose
006. Viết docker-compose
Chúng ta sẽ viết
sudo chmod +x /usr/local/bin/docker-compose
01 trước để có cái nhìn tổng quan về các services trong project nhé- Phiên bản của
0version: '3.5'
version: '3.5'
- Liệt kê các services
services:
mysql:
...
...
...
app:
...
...
...
- Cài đặt cho từng services
mysql:
image: mysql:5.7
container_name: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- docker/database:/var/lib/mysql
☑ image: Chỉ định
sudo chmod +x /usr/local/bin/docker-compose
03 để khởi động version: '3.5'
2, ở đây ta dùng image có sẵn như đã nói ở mục 4.☑ container_name: Chỉ định tên container tùy chỉnh, thay vì tên mặc định.
☑ restart: Giá trị mặc định là
sudo chmod +x /usr/local/bin/docker-compose
05, còn nếu bạn đặt là sudo chmod +x /usr/local/bin/docker-compose
06 thì container sẽ khởi động lại nếu mã thoát cho biết lỗi không thành công.☑ environment: Thêm các biến môi trường
☑ volumes: Chia sẻ dữ liệu giữa container [máy ảo] và host [máy thật] hoặc giữa các container với nhau.
Ví dụ:
- Khi
5 tạo và lưu dữ liệu thì dữ liệu này sẽ lưu ở trong thư mụcservices: mysql: ... ... ... app: ... ... ...
08 của container. Như vậy nếu như container này bị xóa đi thì chúng ta sẽsudo chmod +x /usr/local/bin/docker-compose
09sudo chmod +x /usr/local/bin/docker-compose
Ôi buồn quá -_- Làm gì bây giờ ?
Giải pháp là chúng ta sẽ
10 dữ liệu đó ra ngoài máy host, như vậy khi container bị xóa, dữ liệu sẽ vẫn được lưu trữ ở máy host. Và ở khi bật lại container, dữ liệu lại được mount từ máy host vào trong container và chúng ta tiếp tục sử dụng nó bình thường.sudo chmod +x /usr/local/bin/docker-compose
Thư mục lưu trữ data ở ngoài máy host sẽ không được
11 vào git, ta đưa nó vào gitignore.sudo chmod +x /usr/local/bin/docker-compose
# Ignore data backup docker/database
Ở một số hướng dẫn có lưu dữ liệu backup vào trong thư mục mà framework đã
12 sẵn, ví dụ như đối vớisudo chmod +x /usr/local/bin/docker-compose
13 làsudo chmod +x /usr/local/bin/docker-compose
14 hoặc lưu ở ngoài thư mục dự án thì không cầnsudo chmod +x /usr/local/bin/docker-compose
12 nó nữa.sudo chmod +x /usr/local/bin/docker-compose
app:
container_name: app
build: .
volumes:
- .:/my_app
ports:
- "3000:3000"
environment:
DATABASE_HOST: mysql
DATABASE_USER_NAME: root
DATABASE_PASSWORD: root
☑ build: Sử dụng khi chúng ta không xây dựng
version: '3.5'
2 từ sudo chmod +x /usr/local/bin/docker-compose
03 có sẵn nữa mà xây dựng nó từ version: '3.5'
8.- Nếu
8 nằm cùng thư mục vớiversion: '3.5'
01 thì chỉ cầnsudo chmod +x /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
0- Nếu bạn muốn đặt
8 trong thư mụcversion: '3.5'
22 để cùng vớisudo chmod +x /usr/local/bin/docker-compose
23 cho gọn thì sửa thànhsudo chmod +x /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
1☑ ports: Cấu hình cổng kết nối
Có thể chỉ định cả 2 cổng [HOST:CONTAINER] tức là [cổng ở máy thật: cổng ở máy ảo] hoặc chỉ định mình cổng cho máy ảo thôi.
Ví dụ:
sudo chmod +x /usr/local/bin/docker-compose
24 Khi bạn truy cập vào cổng sudo chmod +x /usr/local/bin/docker-compose
25 ở máy thật thì sẽ được trỏ tới truy cập ở cổng sudo chmod +x /usr/local/bin/docker-compose
26 của máy ảo.☑ environment: Bổ sung các biến môi trường.
Lưu ý rằng
sudo chmod +x /usr/local/bin/docker-compose
27 chính là tên của service mysql.Mình đã push code lên Github.
7. Viết Dockerfile
-> Bây giờ ta sẽ viết
version: '3.5'
8 cho container sudo chmod +x /usr/local/bin/docker-compose
29 trên kia nhé, chỗ mà sudo chmod +x /usr/local/bin/docker-compose
30 ấy.Image cơ sở
2sudo chmod +x /usr/local/bin/docker-compose
Đánh dấu lãnh thổ chút
3sudo chmod +x /usr/local/bin/docker-compose
Cặt đặt các phần mềm cần thiết cho máy ảo
4sudo chmod +x /usr/local/bin/docker-compose
Set timezone cho máy ảo [Optional]
5sudo chmod +x /usr/local/bin/docker-compose
Chỉ định thư mục làm việc mặc định [Optional]
6sudo chmod +x /usr/local/bin/docker-compose
Cài đặt framework cần thiết cho dự án
7sudo chmod +x /usr/local/bin/docker-compose
Copy tất cả dữ liệu tự máy host vào trong container
8sudo chmod +x /usr/local/bin/docker-compose
Cấu hình file
23sudo chmod +x /usr/local/bin/docker-compose
9sudo chmod +x /usr/local/bin/docker-compose
Thiết lập câu lệnh mặc định sẽ chạy khi khởi động
2version: '3.5'
0docker-compose --version
-> Mình có push code mẫu lên Github
8. Viết entrypoint.sh
-> Chạy
sudo chmod +x /usr/local/bin/docker-compose
33 với bash chứ ko phải là sh hay zshdocker-compose --version
1-> Xóa tiến trình cũ
docker-compose --version
2Mỗi khi khởi chạy
34 sẽ có một mãsudo chmod +x /usr/local/bin/docker-compose
35 được sinh ra và lưu vào filesudo chmod +x /usr/local/bin/docker-compose
36 để đánh dấu rằng đã tồn tại tiến trình rails đang chạy.sudo chmod +x /usr/local/bin/docker-compose
Khi bạn stop
34 thì rails sẽ xóa nội dung file này, tuy nhiên trong trường hợp bạnsudo chmod +x /usr/local/bin/docker-compose
38 thì rails server sẽ bị stop mà chưa kịp xóa nội dung file, và khi bạn start lại server thì sẽ gặp lỗisudo chmod +x /usr/local/bin/docker-compose
3docker-compose --version
Như vậy, ta sẽ xóa thủ công nó luôn để đảm bảo không gặp lỗi này, gọi là chặn từ lúc trứng nước.
-> Thực thi câu lệnh truyền vào.
docker-compose --version
4Mình có push code mẫu lên Github
9. Sử dụng docker-compose
9.1 Trường hợp tạo dự án mới
sudo chmod +x /usr/local/bin/docker-compose
39- Chạy câu lệnh sau để initialize project, khi đó các file, folder sẽ tự động được sinh ra:
5docker-compose --version
sudo chmod +x /usr/local/bin/docker-compose
40Khi đó, chúng ta sẽ không cài Rails vào máy thật nữa.
Hãy run một
2 đã càiversion: '3.5'
13 lên và chạy câu lệnh trên bên trongsudo chmod +x /usr/local/bin/docker-compose
2 đó, rồi mount các file, folder của framework được vừa được tạo ra ngoài máy host.version: '3.5'
Ở đây, container đó chính là container
29 mà ta vừa xây dựng ở trên.sudo chmod +x /usr/local/bin/docker-compose
Cú pháp để chạy một câu lệnh bên trong
2 như sau:version: '3.5'
6docker-compose --version
Như vậy, bạn hãy chạy:
7docker-compose --version
- Việc này sẽ mấy chút thời gian, trong quá trình chờ đợi thì bạn nên theo dõi log ở Terminal để xem các bước Docker thực hiện như thế nào nhé !
sudo chmod +x /usr/local/bin/docker-compose
46Nếu bạn cài Rails trực tiếp trên máy thật thì đã có sẵn phiên bản của Ruby [ngôn ngữ lập trình] và Rails [framework của ngôn ngữ] rồi, ví dụ:
8docker-compose --version
Còn như ở Dockerfile phía trên, chúng ta mới chỉ có
2sudo chmod +x /usr/local/bin/docker-compose
chứ chưa cài đặt Rails.
Thứ hai là khi build image, ở step
0docker-compose version 1.23.1, build b02f1306
có nghĩa là copy Gemfile từ máy host vào container thì chúng ta chưa có file này ở máy host:
Như thế sẽ gặp lỗi:
47sudo chmod +x /usr/local/bin/docker-compose
Vậy nên, chúng ta tạo thêm 2 file: Gemfile và Gemfile.lock
Gemfile:
1docker-compose version 1.23.1, build b02f1306
Gemfile.lock
2docker-compose version 1.23.1, build b02f1306
Rồi sau đó hẵng chạy lại câu lệnh
7docker-compose --version
Mình đã push code mẫu lên Github rồi nhé, bởi vì đây là config thư viện của Rails nên không giới thiệu chung với các config của Docker.
sudo chmod +x /usr/local/bin/docker-compose
48- Có thể bạn đã biết, mặc định thì docker chạy với
49 nên những file, folder nó tạo ra [sau khisudo chmod +x /usr/local/bin/docker-compose
50 từsudo chmod +x /usr/local/bin/docker-compose
2 ra máyversion: '3.5'
52] cũng ở quyềnsudo chmod +x /usr/local/bin/docker-compose
53.sudo chmod +x /usr/local/bin/docker-compose
Vậy nên khi bạn dùng editor để
54 những file này thìsudo chmod +x /usr/local/bin/docker-compose
55 sẽ thông báo.sudo chmod +x /usr/local/bin/docker-compose
4docker-compose version 1.23.1, build b02f1306
Giải pháp thì set lại quyền cho nó thôi
5docker-compose version 1.23.1, build b02f1306
sudo chmod +x /usr/local/bin/docker-compose
56- Đối với
57 thì config này nằm ở filesudo chmod +x /usr/local/bin/docker-compose
58sudo chmod +x /usr/local/bin/docker-compose
Sửa từ
docker-compose version 1.23.1, build b02f1306
6thành
docker-compose version 1.23.1, build b02f1306
7- Xong xuôi thì bạn chuyển qua mục 10.2 được rồi.
9.2 Trường hợp cho dự án đang phát triển
sudo chmod +x /usr/local/bin/docker-compose
59- Chỉnh sửa file
60 cho phù hợp nếu cần [ví dụ với Rails: config/database.yml ]sudo chmod +x /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
61Cú pháp
8docker-compose version 1.23.1, build b02f1306
Nếu gặp lỗi này
9docker-compose version 1.23.1, build b02f1306
Do một số file trong thư mục
62 cần quyềnsudo chmod +x /usr/local/bin/docker-compose
53 để truy cập, hãy đổi thànhsudo chmod +x /usr/local/bin/docker-compose
0//hub.docker.com/_/mysql/
sudo chmod +x /usr/local/bin/docker-compose
64Cú pháp
1//hub.docker.com/_/mysql/
Nếu gặp lỗi này
Do một số file trong thư mục
sudo chmod +x /usr/local/bin/docker-compose
62 cần quyền sudo chmod +x /usr/local/bin/docker-compose
53 để truy cập, hãy đổi thành//hub.docker.com/_/mysql/
2Màn hình log:
sudo chmod +x /usr/local/bin/docker-compose
65Òa, log bắn ra ầm ầm, kệ nó đi, bạn vào địa chỉ :
và tận hưởng thành quả nào:
Tạo cơ sở dữ liệu
3//hub.docker.com/_/mysql/
Với mỗi framework sẽ có cách khác nhau để tạo
66.sudo chmod +x /usr/local/bin/docker-compose
6docker-compose --version
Còn đối với rails, nếu ở máy thật, bạn cần gõ 2 câu lệnh sau để tạo database:
5//hub.docker.com/_/mysql/
Còn bây giờ, chúng ta hãy truy cập vào máy ảo để chạy câu lệnh này, bằng cách
Và ở đây, ta cần:
- Truy cập vào
67 nàosudo chmod +x /usr/local/bin/docker-compose
6//hub.docker.com/_/mysql/
- Truy cập vào
Lưu ý
Nếu vừa rồi bạn ấn
68 để dừngsudo chmod +x /usr/local/bin/docker-compose
69 thì khi chạy câu lệnh tạo cơ sở dữ liệu sẽ gặp lỗisudo chmod +x /usr/local/bin/docker-compose
Vì sao ?
- Nhìn vào log trên ta sẽ thấy
Tức là
70 đã bị dừng lại, vậy nênsudo chmod +x /usr/local/bin/docker-compose
71 của chúng ta không thể kết nối tớisudo chmod +x /usr/local/bin/docker-compose
72.sudo chmod +x /usr/local/bin/docker-compose
Để giải quyết điều này thì có nhiều cách:
7//hub.docker.com/_/mysql/
Đơn giản nhất là bạn giữ nguyên tab đang chạy
69 và mở thêm tab để chạy migrate data.sudo chmod +x /usr/local/bin/docker-compose
Dùng option
74sudo chmod +x /usr/local/bin/docker-compose
Thay đổi cách khởi động các
2 thủ côngversion: '3.5'
Bài cũng đã dài, chúng ta sẽ tìm hiểu cách 3 ở phần 4 nhé, đây cũng là cách khuyến khích sử dụng.
- Thay đổi cách khởi động các
2 bằngversion: '3.5'
77sudo chmod +x /usr/local/bin/docker-compose
- Cách này không khuyến khích [Cũng sẽ giải thích ở phần 4 luôn]
- Cũng đủ kiến thức cơ bản về
0 rồiversion: '3.5'
- Nếu bạn gặp lỗi hoặc bị vướng ở đoạn nào chưa hiểu thì hãy để lại bình luận bên dưới, mình sẽ support nếu có thể nhé !