Dockerfile

Dockerfile

30.09.2024
Author: ADMIN

Dockerfile là một tập lệnh chứa các hướng dẫn để xây dựng một Docker image. Dưới đây là các thành phần chính và cách sử dụng chúng:

  1. FROM
FROM <image>:<tag>
  • Đây là lệnh bắt buộc và phải là lệnh đầu tiên trong Dockerfile (trừ ARG).
  • Xác định image cơ sở để bắt đầu xây dựng.
  • Ví dụ: FROM ubuntu:20.04 hoặc FROM python:3.9-alpine
  1. LABEL
LABEL <key>=<value>
  • Thêm metadata vào image.
  • Ví dụ: LABEL version="1.0" maintainer="example@email.com"
  1. ENV
ENV <key>=<value>
  • Đặt biến môi trường.
  • Ví dụ: ENV PATH=/usr/local/bin:$PATH
  1. ARG
ARG <name>[=<default value>]
  • Định nghĩa biến được sử dụng trong quá trình build.
  • Ví dụ: ARG VERSION=latest
  1. WORKDIR
WORKDIR /path/to/directory
  • Đặt thư mục làm việc cho các lệnh RUN, CMD, ENTRYPOINT, COPY và ADD tiếp theo.
  • Ví dụ: WORKDIR /app
  1. COPY
COPY <src> <dest>
  • Sao chép files hoặc thư mục từ máy host vào image.
  • Ví dụ: COPY . /app
  1. ADD
ADD <src> <dest>
  • Tương tự COPY, nhưng có thêm chức năng như giải nén tệp tar hoặc tải file từ URL.
  • Ví dụ: ADD https://example.com/big.tar.xz /usr/src/things/
  1. RUN
RUN <command>
  • Thực thi lệnh và tạo một layer mới.
  • Ví dụ: RUN apt-get update && apt-get install -y python3
  1. CMD
CMD ["executable","param1","param2"]
  • Cung cấp lệnh mặc định để chạy container.
  • Chỉ có thể có một CMD trong Dockerfile.
  • Ví dụ: CMD ["python", "app.py"]
  1. ENTRYPOINT
ENTRYPOINT ["executable", "param1", "param2"]
  • Cấu hình container để chạy như một executable.
  • Ví dụ: ENTRYPOINT ["python", "app.py"]
  1. EXPOSE
EXPOSE <port> [<port>/<protocol>...]
  • Khai báo cổng mà container sẽ lắng nghe khi chạy.
  • Ví dụ: EXPOSE 80 hoặc EXPOSE 80/tcp
  1. VOLUME
VOLUME ["/data"]
  • Tạo một mount point và đánh dấu nó là chứa dữ liệu được mount từ bên ngoài.
  • Ví dụ: VOLUME ["/var/log"]
  1. USER
USER <user>[:<group>]
  • Đặt user (hoặc UID) và tùy chọn USER group (hoặc GID) để chạy các lệnh tiếp theo.
  • Ví dụ: USER nginx
  1. HEALTHCHECK
HEALTHCHECK [OPTIONS] CMD command
  • Kiểm tra sức khỏe của container.
  • Ví dụ: HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
  1. SHELL
SHELL ["executable", "parameters"]
  • Ghi đè shell mặc định được sử dụng cho lệnh shell form của RUN, CMD, ENTRYPOINT.
  • Ví dụ: SHELL ["/bin/bash", "-c"]
  1. STOPSIGNAL
STOPSIGNAL signal
  • Đặt tín hiệu hệ thống để gửi đến container để thoát.
  • Ví dụ: STOPSIGNAL SIGTERM

Một Dockerfile điển hình có thể kết hợp nhiều lệnh này để xây dựng một image phức tạp. Ví dụ:

FROM python:3.9-slim
LABEL maintainer="example@email.com"

ENV PYTHONUNBUFFERED 1

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

Mỗi lệnh trong Dockerfile tạo ra một layer mới trong image. Việc hiểu và sử dụng đúng các lệnh này sẽ giúp bạn tạo ra các Docker images hiệu quả và tối ưu.

Docker là gì?

Docker là gì?

30.09.2024
Author: ADMIN

Docker là một nền tảng mã nguồn mở được sử dụng để phát triển, vận chuyển và chạy các ứng dụng. Nó cho phép bạn tách biệt ứng dụng của mình khỏi cơ sở hạ tầng để có thể nhanh chóng phân phối phần mềm. Dưới đây là những điểm chính để hiểu về Docker:

  1. Containerization (Ảo hóa container):

    • Docker sử dụng công nghệ container để đóng gói một ứng dụng và tất cả các phụ thuộc của nó vào một “container” ảo.
    • Mỗi container là một đơn vị phần mềm tiêu chuẩn hóa, chứa mọi thứ cần thiết để chạy ứng dụng: mã, runtime, công cụ hệ thống, thư viện và cài đặt.
  2. Nhẹ và hiệu quả:

    • Khác với máy ảo truyền thống, các container Docker chia sẻ kernel của hệ điều hành máy chủ, làm cho chúng nhẹ hơn và sử dụng tài nguyên hiệu quả hơn.
  3. Tính nhất quán:

    • Docker đảm bảo rằng ứng dụng sẽ chạy giống nhau trong mọi môi trường, từ máy phát triển đến máy chủ sản xuất.
  4. Các thành phần chính:

    • Docker Engine: Nền tảng chạy và quản lý các container.
    • Docker Image: Bản mẫu chỉ đọc chứa hướng dẫn để tạo container.
    • Docker Container: Phiên bản chạy của một image.
    • Dockerfile: File văn bản chứa các lệnh để xây dựng một Docker image.
    • Docker Hub: Kho lưu trữ công cộng cho Docker images.
  5. Lợi ích:

    • Triển khai nhanh chóng và dễ dàng
    • Tính di động cao
    • Quản lý phiên bản và thành phần hiệu quả
    • Tái sử dụng và chia sẻ
    • Cô lập và bảo mật
  6. Ứng dụng:

    • Phát triển và kiểm thử phần mềm
    • Triển khai ứng dụng microservices
    • Tự động hóa quy trình CI/CD
    • Mở rộng quy mô ứng dụng

Docker đã trở thành một công cụ quan trọng trong ngành công nghiệp phần mềm, giúp đơn giản hóa quá trình phát triển, triển khai và quản lý ứng dụng trong các môi trường khác nhau.

Hãy xem xét một ví dụ cụ thể về việc sử dụng Docker để containerize một ứng dụng web đơn giản bằng Python Flask. Chúng ta sẽ đi qua các bước từ việc tạo ứng dụng đến việc chạy nó trong một container Docker.

  1. Tạo ứng dụng Flask đơn giản:

Đầu tiên, tạo một thư mục cho dự án và tạo file app.py:

 from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return "Xin chào từ Docker container!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
 
  1. Tạo file requirements.txt:
Flask==2.0.1
  1. Tạo Dockerfile:
# Sử dụng image Python chính thức làm base image
FROM python:3.9-slim

# Đặt thư mục làm việc trong container
WORKDIR /app

# Sao chép file requirements.txt vào container
COPY requirements.txt .

# Cài đặt các dependencies
RUN pip install --no-cache-dir -r requirements.txt

# Sao chép mã nguồn ứng dụng vào container
COPY . .

# Mở cổng 5000 để Flask app có thể truy cập được
EXPOSE 5000

# Chạy ứng dụng khi container được khởi động
CMD ["python", "app.py"]
  1. Build Docker image:

Mở terminal, di chuyển đến thư mục dự án và chạy lệnh:

docker build -t flask-hello-world .
  1. Chạy Docker container:

Sau khi build xong, chạy container với lệnh:

docker run -d -p 5000:5000 flask-hello-world

Bây giờ, bạn có thể truy cập ứng dụng tại http://localhost:5000 trên trình duyệt.

  1. Kiểm tra container đang chạy:
docker ps
  1. Dừng container:
docker stop <container_id>

Giải thích chi tiết:

  • Dockerfile định nghĩa cách xây dựng image:

    • FROM python:3.9-slim: Sử dụng image Python 3.9 nhẹ làm cơ sở.
    • WORKDIR /app: Đặt thư mục làm việc trong container.
    • COPY requirements.txt .: Sao chép file requirements vào container.
    • RUN pip install ...: Cài đặt các dependencies.
    • COPY . .: Sao chép toàn bộ mã nguồn vào container.
    • EXPOSE 5000: Khai báo cổng 5000 sẽ được sử dụng.
    • CMD ["python", "app.py"]: Xác định lệnh để chạy ứng dụng.
  • Lệnh docker build tạo một image từ Dockerfile.

  • Lệnh docker run tạo và chạy một container từ image:

    • -d: Chạy container ở chế độ detached (nền).
    • -p 5000:5000: Map cổng 5000 của máy host với cổng 5000 của container.

Ví dụ này minh họa cách Docker có thể được sử dụng để đóng gói một ứng dụng web đơn giản cùng với tất cả dependencies của nó, đảm bảo rằng nó có thể chạy một cách nhất quán trên bất kỳ môi trường nào có Docker.

Life Cycle Laravel

Life Cycle Laravel

27.09.2024
Author: ADMIN

Laravel, một framework PHP phổ biến, có một vòng đời (life cycle) riêng cho mỗi request. Hãy cùng xem qua các giai đoạn chính trong vòng đời của một request trong Laravel:

  1. Entry Point (Điểm vào)

Tất cả các requests đều đi qua file public/index.php:

<?php

use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;

define('LARAVEL_START', microtime(true));

require __DIR__.'/../vendor/autoload.php';

$app = require_once __DIR__.'/../bootstrap/app.php';

$kernel = $app->make(Kernel::class);

$response = $kernel->handle(
    $request = Request::capture()
)->send();

$kernel->terminate($request, $response);
  1. Autoloading

Composer’s autoloader được load.

  1. Create Application Instance

Một instance của ứng dụng Laravel được tạo ra.

  1. Kernel

HTTP Kernel hoặc Console Kernel được tạo ra, tùy thuộc vào loại request.

  1. Service Providers
public function register()
{
    //
}

public function boot()
{
    //
}

Service Providers được đăng ký (register) và khởi động (boot).

  1. Middleware

Request đi qua global middleware:

protected $middleware = [
    \App\Http\Middleware\TrustProxies::class,
    \App\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
  1. Routing

Router xác định route phù hợp và chạy route middleware:

Route::get('/user', 'UserController@index')->middleware('auth');
  1. Controller

Controller xử lý request và trả về response:

public function index()
{
    return view('users.index', ['users' => User::all()]);
}
  1. Response

Response được gửi trở lại cho client.

  1. Termination

Sau khi response được gửi, các termination tasks được thực hiện:

$kernel->terminate($request, $response);

Hiểu rõ về vòng đời này sẽ giúp bạn can thiệp vào đúng thời điểm trong quá trình xử lý request, ví dụ như đăng ký service providers, thêm middleware, hoặc xử lý logic trong controllers.

Life Cycle JavaScript

Life Cycle JavaScript

27.09.2024
Author: ADMIN

Thực tế, JavaScript không có một “vòng đời” cụ thể như một số ngôn ngữ lập trình khác, nhưng chúng ta có thể nói về vòng đời của một script JavaScript khi nó được thực thi trong trình duyệt web. Dưới đây là mô tả về quá trình này:

  1. Tải trang (Page Load)
// Khi trang HTML được tải, các thẻ <script> được xử lý
<script src="myScript.js"></script>
  1. Phân tích cú pháp (Parsing)

JavaScript engine phân tích cú pháp của code.

  1. Biên dịch (Compilation)

Code được biên dịch thành bytecode.

  1. Thực thi (Execution)
// Code được thực thi từ trên xuống dưới
console.log("Hello, World!");
  1. Xử lý sự kiện (Event Handling)
// Các event listeners được đăng ký
document.getElementById("myButton").addEventListener("click", function() {
    console.log("Button clicked!");
});
  1. Asynchronous Operations
// Các hoạt động bất đồng bộ được xử lý
setTimeout(function() {
    console.log("This runs after 2 seconds");
}, 2000);
  1. Garbage Collection
// Bộ nhớ không còn sử dụng được giải phóng tự động
let obj = { name: "John" };
obj = null; // Đối tượng ban đầu có thể được thu gom rác
  1. Đóng trang (Page Unload)
// Có thể đăng ký các hàm để chạy khi trang đóng
window.addEventListener("beforeunload", function() {
    console.log("Page is about to unload");
});

Lưu ý rằng trong môi trường Node.js, vòng đời sẽ hơi khác, tập trung vào việc xử lý các module và event loop.

Hiểu về vòng đời này giúp bạn tối ưu hóa hiệu suất và quản lý tài nguyên tốt hơn trong ứng dụng JavaScript của mình.

AWS Region

AWS Region

27.09.2024
Author: ADMIN

AWS Region là gì?

AWS Region là một khu vực địa lý riêng biệt trên thế giới, nơi Amazon Web Services (AWS) triển khai và vận hành cơ sở hạ tầng điện toán đám mây của mình. Mỗi Region là một tập hợp các trung tâm dữ liệu được tổ chức thành các Availability Zones (AZs).

Đặc điểm chính của AWS Region:

  1. Độc lập về mặt địa lý: Mỗi Region hoàn toàn tách biệt và độc lập với các Region khác.

  2. Nhiều Availability Zones: Mỗi Region thường có ít nhất 3 AZs, đảm bảo tính sẵn sàng cao.

  3. Dịch vụ đa dạng: Hầu hết các dịch vụ AWS đều có sẵn trong mỗi Region, nhưng một số dịch vụ có thể chỉ khả dụng ở một số Region nhất định.

  4. Tuân thủ quy định: Các Region được thiết kế để đáp ứng các yêu cầu tuân thủ và quy định cụ thể của từng khu vực.

  5. Giá cả khác nhau: Chi phí sử dụng dịch vụ có thể khác nhau giữa các Region.

Tại sao AWS có nhiều Region?

  1. Giảm độ trễ: Đặt các dịch vụ gần với người dùng cuối giúp cải thiện hiệu suất.

  2. Tuân thủ quy định: Một số quốc gia yêu cầu dữ liệu phải được lưu trữ trong nước.

  3. Khả năng phục hồi sau thảm họa: Nhiều Region giúp tăng cường khả năng phục hồi và liên tục kinh doanh.

  4. Tối ưu hóa chi phí: Cho phép khách hàng chọn Region có chi phí phù hợp nhất.

Lựa chọn Region phù hợp:

Khi chọn Region, cần xem xét:

  1. Vị trí địa lý: Chọn Region gần nhất với người dùng cuối.

  2. Tuân thủ: Đảm bảo Region đáp ứng các yêu cầu pháp lý và quy định.

  3. Dịch vụ có sẵn: Kiểm tra xem các dịch vụ cần thiết có sẵn trong Region đó không.

  4. Chi phí: So sánh giá cả giữa các Region.

  5. Độ trễ: Đánh giá độ trễ mạng từ Region đến người dùng cuối.

Lưu ý quan trọng:

  • Dữ liệu và tài nguyên trong một Region không tự động sao chép sang Region khác.
  • Một số dịch vụ AWS có phạm vi toàn cầu (như IAM, Route 53), trong khi hầu hết các dịch vụ khác có phạm vi Region.
  • Luôn chọn đúng Region trước khi bắt đầu triển khai tài nguyên để tránh sai sót và tối ưu hóa hiệu suất.

Hiểu rõ về AWS Region sẽ giúp bạn thiết kế và triển khai các ứng dụng đám mây hiệu quả, đảm bảo tính sẵn sàng cao và tuân thủ các yêu cầu kinh doanh cũng như quy định pháp lý.

AWS S3

AWS S3

27.09.2024
Author: ADMIN

AWS S3 (Simple Storage Service) là một dịch vụ lưu trữ đối tượng được cung cấp bởi Amazon Web Services. Đây là một trong những dịch vụ cốt lõi và phổ biến nhất của AWS. Hãy tìm hiểu chi tiết về AWS S3:

AWS S3 là gì?

AWS S3 là dịch vụ lưu trữ đối tượng có khả năng mở rộng cao, cung cấp khả năng lưu trữ và truy xuất dữ liệu từ bất kỳ đâu trên web. S3 được thiết kế để cung cấp độ bền 99,999999999% (11 số 9) và khả năng sẵn sàng 99,99% cho dữ liệu của bạn.

Đặc điểm chính của AWS S3:

  1. Lưu trữ đối tượng: S3 lưu trữ dữ liệu dưới dạng đối tượng trong các “bucket”.

  2. Khả năng mở rộng: Có thể lưu trữ và truy xuất bất kỳ lượng dữ liệu nào, bất kỳ lúc nào.

  3. Độ bền cao: Được thiết kế để cung cấp độ bền 99,999999999%.

  4. Bảo mật: Cung cấp nhiều tính năng bảo mật mạnh mẽ.

  5. Linh hoạt: Hỗ trợ nhiều lớp lưu trữ khác nhau cho các nhu cầu khác nhau.

  6. Quản lý dễ dàng: Cung cấp giao diện quản lý trực quan và API đa dạng.

Các khái niệm cơ bản trong S3:

  1. Bucket: Là container chứa các đối tượng. Mỗi đối tượng được lưu trữ trong một bucket.

  2. Object: Là đơn vị cơ bản của dữ liệu được lưu trữ trong S3. Mỗi object bao gồm dữ liệu và metadata.

  3. Key: Là tên duy nhất được gán cho một object trong bucket.

  4. Versioning: Cho phép lưu trữ nhiều phiên bản của cùng một object.

  5. Storage Classes: Các lớp lưu trữ khác nhau cho các nhu cầu truy cập và chi phí khác nhau.

Các lớp lưu trữ S3:

  1. S3 Standard: Cho dữ liệu truy cập thường xuyên.
  2. S3 Intelligent-Tiering: Tự động tối ưu chi phí cho dữ liệu có mẫu truy cập không xác định.
  3. S3 Standard-IA: Cho dữ liệu truy cập ít thường xuyên.
  4. S3 One Zone-IA: Tương tự Standard-IA nhưng chỉ lưu trữ trong một AZ.
  5. S3 Glacier: Cho lưu trữ dài hạn với chi phí thấp.
  6. S3 Glacier Deep Archive: Cho lưu trữ dài hạn với chi phí cực thấp.

Ứng dụng phổ biến của S3:

  1. Lưu trữ và phân phối nội dung
  2. Backup và khôi phục dữ liệu
  3. Lưu trữ dữ liệu cho phân tích Big Data
  4. Lưu trữ log files
  5. Hosting website tĩnh
  6. Lưu trữ dữ liệu gốc cho các ứng dụng cloud-native

Tính năng bảo mật:

  • Mã hóa phía máy chủ và phía khách hàng
  • Quản lý quyền truy cập bằng IAM và bucket policies
  • Versioning để bảo vệ khỏi xóa hoặc ghi đè ngoài ý muốn
  • MFA Delete để ngăn chặn xóa dữ liệu không mong muốn

AWS S3 là một dịch vụ cực kỳ linh hoạt và mạnh mẽ, được sử dụng rộng rãi trong nhiều ứng dụng và giải pháp cloud. Hiểu rõ về S3 sẽ giúp bạn tận dụng tối đa khả năng lưu trữ và quản lý dữ liệu trong môi trường AWS.

Config S3

Task 1: Tạo Bucket trên S3

  1. Truy cập Storage >> S3 từ menu Services

2. Tại giao diện của S3, nhấn chọn Create bucket và điền lần lượt vào các trường sau cho bucket details.

  • Bucket name: đặt tên cho bucket (S3 bucket name mang tính định danh trên tất cả các region của AWS nên phải duy nhất và không trùng lặp).

  • Region: Chọn Singapore (ap-southeast-1)

  • Object ownership: Chọn ACLs enabled

    • Object ownership: Chọn Object writer (anh em nhớ chọn Object Owner, ngược lại sẽ không có quyền chỉnh sửa bucket ACL)

  • Với thiết lập Block Public Access, để đơn giản anh em bỏ check và xác nhận vào mục acknowleadge nhé (thao tác này đồng nghĩa bật mode public cho bucket).


A screenshot of a computer

Description automatically generated

A screenshot of a computer screen

Description automatically generated

A screenshot of a bucket

Description automatically generated

Những phần khác giữ nguyên như mặc đinh và nhấn Create bucket.

3. Sau khi quá trình taọ bucket hoàn tất, hệ thống sẽ tự động chuyển đến giao diện chứa danh sách tất cả các bucket đang có trong tài khoản AWS của bạn.

A screenshot of a computer

Description automatically generated

Task 2: Upload object lên S3 Bucket

  1. Nhấn vào bucket name để, ngay tại tab Object, nhấn vào upload.

A screenshot of a computer

Description automatically generated

  1. Tại giao diện kế tiếp, nhấn add file và chọn một hoặc nhiều file từ local và nhấn Upload.

A screenshot of a computer

Description automatically generated

3. Sau khi quá trình upload hoàn tất sẽ hiện thông báo kèm danh sách các object tương tự như ví dụ bên dưới.

 

A screenshot of a video

Description automatically generated

Task 3: Thay đổi quyền trên Bucket

1. Từ danh sách các object đã tải lên ở phần trước, anh em thử nhấn vào một file bất kỳ, ví dụ Amazon-S3.png để xem chi tiết các thành phần của object này như owner, size, link, …

2. Anh em tìm và copy Object URL (đây là http endpoint của một đối tượng)

A screenshot of a computer

Description automatically generated

3. Tiếp theo, bạn thử mở tab trình duyệt khác và truy cập Object URL này sẽ nhận được thông báo AccessDenied như bên dưới.

 

A screenshot of a computer

Description automatically generated

Lý do khá đơn giản, mặc dù bucket đã được thiếp lập chế độ public lúc khởi tạo nhưng theo mặc định các object sau khi tải lên vẫn ở mode private.

4. Quay lại giao diện Object details của file Amazon-S3.png, chuyển sang tab Permissons, nhấn Edit để thực hiện chỉnh sửa quyền.

A screenshot of a computer

Description automatically generated

5. Tại đây, anh em có thể tùy biến quyền cho một số nhóm khác nhau. Ví dụ trong bài lab này mình sẽ gán quyền read only lên Object Amazon-S3.png cho tất cả (everyone).

A screenshot of a computer

Description automatically generated

Nhớ xác nhận vào checkbox I understand the effects of these changes on
this object, sau đó nhấn Save changes để cập nhật thay đổi.

6. Bây giờ, thử lại bước 3 – truy cập Object URL sẽ hiện được nội dung ảnh Amazon-S3.png từ trình duyệt web.

Task 4: Tạo Bucket Policy

Trong Task 3, anh em chỉ gán quyền cho một object nhất định. Trong phần này, nếu có nhu cầu gán quyền tương tự cho tất cả các đối tượng có trong bucket thì sẽ làm thế nào? Câu trả lời là ta sẽ tạo một Bucket policy.

1. Quay trở lại giao diện chứa danh sách bucket, nhấn chọn vào bucket name hiepsharing-saa-b-1, vẫn chuyển sang tab Permissions.

2. Kéo xuống tại mục Bucket policy, nhấn Edit để mở trình soạn thảo Bucket policy editor (dĩ nhiên trống không 😆 ).

Lưu ý: Bucket policy được trình bày dưới dạng ngôn ngữ JSON nên anh em có thể chủ động nghiên cứu thêm bằng 2 công cụ Policy examples hoặc Policy generator được AWS  cung cấp.

Hoặc đơn giản trong bài lab này, anh em có thể copy và dán JSON bên dưới vào và thay thế phần Resources bằng chính Bucket ARN của anh em.

ras.vending là bucket name

Với nội dung JSON  trên, mình muốn tạo ra một bucket  policy cho phép mọi người có quyền truy cập tất cả các object có trong bucket ras.vending

A screenshot of a computer

Description automatically generated

Xem kỹ lại cú pháp của JSON, nếu không có lỗi gì (Errors: 0), nhấn Save changes để tạo policy.

Task 5: Kiểm tra hoạt động của Bucket Policy

1. Sau khi thiết lập bucket policy thành công, quay lại danh sách các object đã tải lên ở phần trước, tick chọn vào file test_upload.txt (chưa cấu hình object permission trước đó), nhấn Copy URL.

A screenshot of a computer

Description automatically generated

2. Mở một tab trình duyệt khác và dán Object URL để truy cập vào nội dung file test_upload.txt trên bucket hiepsharing-saa-b-1. Kết quả như minh họa bên dưới chứng tỏ bucket policy chúng ta tạo ở phần trước thành công.