-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontent.json
More file actions
1 lines (1 loc) · 227 KB
/
content.json
File metadata and controls
1 lines (1 loc) · 227 KB
1
{"meta":{"title":"Bài viết Tiển Nguyễn","subtitle":"Bài viết nhanh từ Tiển Nguyễn.","description":"Những ghi chú hỗ trợ gợi nhớ trong quá trình phát triển.","author":"nguyenvantien2009","url":"http://nguyenvantien2009.com","root":"/viet/"},"pages":[],"posts":[{"title":"Chuyển đổI Dữ Liệu đA Không Gian Nhiều Chiều Sang Một Chiều Trong Pandas DataFrame.","slug":"2022/chuyen-doi-du-lieu-da-chieu-thanh-mot-chieu-trong-dataframe-cua-pandas","date":"2022-07-30T17:00:00.000Z","updated":"2022-07-30T18:05:39.366Z","comments":true,"path":"2022/chuyen-doi-du-lieu-da-chieu-thanh-mot-chieu-trong-dataframe-cua-pandas.html","link":"","permalink":"http://nguyenvantien2009.com/2022/chuyen-doi-du-lieu-da-chieu-thanh-mot-chieu-trong-dataframe-cua-pandas.html","excerpt":"","text":"Dữ liệu trong thực tế có nhiều chiều không gian. Nhưng hầu hết các thuật toán trong học máy chỉ có thể sử dụng dữ liệu trong không gian 2 chiều (2D). Do đó việc chuyển đổi dữ liệu không gian nhiều chiều thành không gian 2 chiều sẽ thường được thấy trong DataFrame của thư viện Pandas. Trong bài viết này tôi có một ví dụ thực tế mà đang thực hiện. Lấy dữ liệu lịch sử truy cập của user sau đó xây dựng một bộ dữ liệu 2D để sử dụng như một dữ liệu huấn luyện trong thật toán học máy. Cụ thể là tính độ tương quan (correlation) giữa các URL mà một user đã gửi http requests đến website. Với ý tưởng là một website được mở thường sẽ đi kèm với các url khác. Nếu độ tương qua này nó không giống nhau hoặc chênh lệch khá lớn thì user đó sẽ bị đánh giá bất thường. Thực hiện chi tiết Lấy dữ liệu của user request thông qua dữ liệu log sau đó tính mối tương quan giữ các URL với nhau thông qua tần suất request trên khung thời gian. DataFrame trên mõi user sẽ được dùng tính mói tương qua. Vậy là ta đó dữ liệu 3 chiều (2 chiều với user request URL và được nâng 3 chiều là mỗi user có danh sách tương quan các URL đó.) Để đưa vào các thật toán học máy thì cần chuyển về 2 chiều. Với X là danh sách các user và y là tuần suất request của user đó theo khung thời gian. Mã nguồn chi tiếtDữ liệu lịch sử truy cập có khá nhiều thông tin nên tôi đã thực hiện bài viết bằng dữ liệu ví dụ. Tại đây ta có dữ liệu truy cập lịch sử của các user (trong cột user), số http request gửi đến website và ngày mà ta đã thống kê. 1234567891011121314151617181920212223import pandas as pddata = [ ['user1', 'url_1', 12, '2022-01-01'], ['user1', 'url_2', 112, '2022-01-02'], ['user1', 'url_2', 11, '2022-01-03'], ['user1', 'url_2', 112, '2022-01-04'], ['user1', 'url_4', 112, '2022-01-04'], ['user1', 'url_2', 112, '2022-01-05'], ['user1', 'url_4', 12, '2022-01-01'], ['user2', 'url_1', 11, '2022-02-01'], ['user4', 'url_3', 1112, '2022-01-01'], ['user3', 'url_2', 10, '2022-01-10'], ['user3', 'url_2', 12, '2022-02-10'], ['user3', 'url_2', 12, '2022-02-11'], ['user3', 'url_2', 1112, '2022-01-01']]df = pd.DataFrame(data=data, columns=[ 'user', 'url', 'number_requests', 'date'])display(df) Tôi sẽ tạo một vòng lập duyệt qua các user để tính độ tương quan các URL của mỗi user. Sử dụng hàm corr() của DataFrame để tính độ tương quan các URL. Vì kết quả của correlation của mỗi user sẽ là một dataframe. Nó là dữ liệu 2D (dữ liệu có thể hiện thị dưới dạng bảng cột và hàng). Để kết hợp dữ liệu với các user khác để tạo nên một bộ dữ liệu cho huấn luyện. 1234567891011121314151617181920212223242526df_train = pd.DataFrame()users = list(set(df['user'])) for u in users: df_user = df[df['user']==u][[ 'url', 'number_requests', 'date' ]] df_user_pivot = df_user.pivot( columns='url', values='number_requests', index='date' ) df_corr = df_user_pivot.corr() df_corr.fillna(0, inplace=True) # convert dataframe to 1 row. df_row = pd.DataFrame(df_corr.stack()).T # set index with user. df_row['user'] = u df_row.set_index('user', inplace=True) # concat dataframe from series row. df_train = pd.concat([df_train, df_row]).fillna(0)# show dataframe for training.display(df_train) Mã nguồn Githubhttps://github.com/nguyenvantien2009/dev-notes-code/blob/main/posts/2022/chuyen-doi-du-lieu-da-chieu-thanh-mot-chieu-trong-dataframe-cua-pandas/sample.py","categories":[],"tags":[{"name":"Machine Learning","slug":"Machine-Learning","permalink":"http://nguyenvantien2009.com/tags/Machine-Learning/"},{"name":"Data Engineer","slug":"Data-Engineer","permalink":"http://nguyenvantien2009.com/tags/Data-Engineer/"},{"name":"Pandas","slug":"Pandas","permalink":"http://nguyenvantien2009.com/tags/Pandas/"}]},{"title":"Thư Viện Trực Quan Hóa Dữ Liệu (Visualization) Trong Python.","slug":"2022/thu-vien-truc-quan-hoa-du-lieu-trong-python","date":"2022-06-22T17:00:00.000Z","updated":"2022-06-24T19:04:16.674Z","comments":true,"path":"2022/thu-vien-truc-quan-hoa-du-lieu-trong-python.html","link":"","permalink":"http://nguyenvantien2009.com/2022/thu-vien-truc-quan-hoa-du-lieu-trong-python.html","excerpt":"","text":"Thư viện trực quan hóa dữ liệu (Visualization) trong Python.Trực quan hóa dữ liệu là một phần không thể thiếu trong các nhà khoa học dữ liệu, những kỹ sư phát triển máy học. Do đó bài viết này sẽ liệt kê các thư viện trực quan dữ liệu trên Python. Nhưng nếu đã tìm hiểu đến bài viết này thì chắc hẳn đã hiểu được mức độ quan trọng trong trực quan hóa dữ liệu. Những thư viện được dùng nhiều.Với tôi thì thích thư viện Plotly nhất. Nó có nhiều loại biểu đồ đã được hỗ trợ sẵn và cũng có mã nguồn ví dụ rõ ràng. Thư viện này cũng có những thư viện trả tiền. Nhưng phiên bản chính vẫn có giấy phép MIT (một giấy phép nguồn mở có thể sử dụng trong phát triển các sản phẩm thương mại). Đường liên kết này là danh sách các loại biểu đồ đang được hỗ trợ trong Plotly https://plotly.com/python/. Thư viện này đơn giản dễ sử dụng. Nhưng với Matplotlib là thư viện được xem là tốt nhất trên Python khi sử dụng trong trực quan hóa dữ liệu. Nhưng giao diện nó không được đẹp lắm. Nhưng nếu cần các tính năng chuyên nghiệp và tùy chỉnh thì có lẻ phải dùng bộ thư viện này. Khi nào nên dùng thư viện nào?Với Matplotlib, đây là một thư viện được cho là lâu nhất là nhiều người sử dụng nhất (nó thường thấy trong các bài viết về khoa học dữ liệu). Nó rất mạnh và cho nhiều tính năng nhất nhưng chính vì thế nó không đơn giản để sử dụng như các thư viện tương tự khác. Nhưng nếu dễ sử dụng và có giao diện đẹp hơn thì dùng Seaborn. Nó được xem là kế thừa trên nền tảng của Matplotlib. Hiện cũng có nhiều bài viết được trình bày trên Seaborn. Với Bokeh, là một thư viện có thế mạnh về biểu diễn biểu đồ, đồ thị… với dự liệu thời gian thực (realtime). Xuất tốt ra các kiểu dữ liệu JSON, HTML và các ứng dụng web. Bokeh được sử dụng với 3 cấp độ. (1) sử dụng đơn giản để tạo các biểu đồ nhanh như bar plot, box plot, histogram… (2) Sử dụng ở mức độ có nhiều tùy chọn tương đương Matplotlib với các biểu đồ như scatter plot. (3) Cuối cùng là sâu hơn dành cho các lập trình viên phần mềm. Không có thiết lập các thông số mặt định mà phải tự định nghĩa mỗi thành phần trong biểu đồ. Với Pygal, thư viện sử dụng khi cần nhúng (embeded) biểu đồ vào trong các trang web. Nó hỗ trợ tốt xuất các tập tin svg nhưng chỉ nên sử dụng trong các trường dữ liệu nhỏ. Nếu lớn mà dùng nó sẽ có thể sẽ chậm chạp trong quá trình thông dịch (render) ra các tập tin (file). Với Plotly, là một nền tảng trực quan dữ liệu trực tuyến (online). Nhưng cũng có thể dùng được khi ngoại tuyến (offline). Nó có thêm các biểu đồ mà các thư viện khác không có như contour plots, dendograms… và các biểu đồ dạng bản đồ địa lý trực tuyến. Nếu cần sử dụng thư viện chuyên về vẽ bản đồ thì Geoplotlib là một thư viện được thiết kế dành riêng cho nó. Nó sẽ biểu diễn dữ liệu của bạn trên bản đồ thế giới. Có thể sẽ dễ sử dụng hơn Plotly nếu chỉ tập trung bản đồ. Thêm một thư viện tốt để vẽ bản đồ và thực hiện các thao tác trên bản đồ và xuất được HTML là Folium (MultiPolyline). Với Missingno, thư viện chuyên sử dụng để tóm tắt (summary) các dữ liệu có trong DataFrame dưới dạng biểu đồ heapmap hay dendrogram. Bài tham khảo 12 Python Data Visualization Libraries to Explore for Business Analysis Example Geo map Folium Plotly Graphing Libraries Python Data Visualization Libraries Top 8 Python Libraries for Data Visualization Data Visualization","categories":[{"name":"Máy học","slug":"May-hoc","permalink":"http://nguyenvantien2009.com/categories/May-hoc/"}],"tags":[{"name":"Visualization","slug":"Visualization","permalink":"http://nguyenvantien2009.com/tags/Visualization/"},{"name":"Data Scientist","slug":"Data-Scientist","permalink":"http://nguyenvantien2009.com/tags/Data-Scientist/"},{"name":"Python Library","slug":"Python-Library","permalink":"http://nguyenvantien2009.com/tags/Python-Library/"}]},{"title":"Sử Dụng Pygal Trong Trực Quan Hóa Dữ Liệu Trong Python.","slug":"2022/su-pyga-la-mot-trong-cac-thu-vien-de-truc-quan-hoa-du-lieu-visulization","date":"2022-06-22T17:00:00.000Z","updated":"2022-06-24T19:38:41.332Z","comments":true,"path":"2022/su-pyga-la-mot-trong-cac-thu-vien-de-truc-quan-hoa-du-lieu-visulization.html","link":"","permalink":"http://nguyenvantien2009.com/2022/su-pyga-la-mot-trong-cac-thu-vien-de-truc-quan-hoa-du-lieu-visulization.html","excerpt":"","text":"Sử dụng Pygal trong trực quan hóa dữ liệu trong Python. Tạo sao dùng nó?Bài viết tham khảo Github Pygal","categories":[{"name":"Máy học","slug":"May-hoc","permalink":"http://nguyenvantien2009.com/categories/May-hoc/"}],"tags":[{"name":"Visualization","slug":"Visualization","permalink":"http://nguyenvantien2009.com/tags/Visualization/"},{"name":"Machine Learning","slug":"Machine-Learning","permalink":"http://nguyenvantien2009.com/tags/Machine-Learning/"},{"name":"Data Scientist","slug":"Data-Scientist","permalink":"http://nguyenvantien2009.com/tags/Data-Scientist/"}]},{"title":"Ghi Lại Thông Số Dữ Liệu Và Kết Quả Của Qui Trình Huấn Luyện Trong MLflow Thông Qua Biểu đồ Hình ảNh.","slug":"2022/ve-va-luu-bieu-do-trong-mlflow","date":"2022-06-04T17:00:00.000Z","updated":"2022-06-05T09:33:47.411Z","comments":true,"path":"2022/ve-va-luu-bieu-do-trong-mlflow.html","link":"","permalink":"http://nguyenvantien2009.com/2022/ve-va-luu-bieu-do-trong-mlflow.html","excerpt":"","text":"Ghi lại thông số dữ liệu và kết quả của qui trình huấn luyện trong MLflow thông qua biểu đồ hình ảnh.Khi làm việc với luồng dữ liệu và quá trình sử lý dữ liệu trong máy học không sớm thì muộn thì chúng ta yêu cầu các biểu đồ để trực quang quá trong quá trình huấn luyện. Nó gần như bắt buộc để chúng ta có thể tin mình đồng thời cũng là tài liệu trực quang để ta thuyết phục đội nhóm lẫn khách hàng… Những hình ảnh, biểu đồ mà ta thường dùng trong các giai đoạn như: biểu đồ phân phối dữ liệu, biểu đồ thể hiện biến đổi điểm số của kết quả huấn luyện, biểu đồ thể hiện tỉ lệ dương tính thật và giả… Và nhiều biểu đồ khác nữa phụ thuộc vào từng thuật toán sử dụng và phụ thuộc vào nhu cầu mà bạn muốn thấy. Những biểu đồ này thường suất hiện trên định dạng hình ảnh như PNG, SVG… Trong MLFlow nó đã hỗ trợ chúng ta ghi lại các biểu đồ đó trong mỗi artifact (nó là một thư mục có cấu trúc theo qui định của MLFlow). Một lệnh log_model sẽ sinh ra thư mục này và lưu toàn bộ kết quả của quá trình huấn luyện. Hình ảnh cũng sẽ được lưu vào thư mục này với lệnh log_figure. Tôi đã thử và nó hoạt động như tôi nghĩ với những gì tôi đã làm bên dưới. Kết quả huấn luyện được ghi trong artifact.Khi nghe ai đó nói về artifact bạn có thể xem nó là một thư mục hay một tập tin nén để đống gối các tập tin, thư mục cần thiết để có thể mang đi chạy (hay sách thường gọi là triển khai hoặc deploy). Trong MLFlow nó là thư mục cũng với ý nghĩa này. Trong nó chứa 2 thành phần quan trọng. 1234567# Directory written by mlflow.sklearn.save_model(model, "my_model")my_model/├── MLmodel├── model.pkl├── conda.yaml├── python_env.yaml└── requirements.txt Một là dump model đã dùng trong huấn luyện. Nó dùng thư viện pickle trong Python. Tôi đang hiểu nó như băm đối tượng đó thành byte để lưu lại trong tập tin được. Model huấn luyện này sẽ được dùng trong dự đoán (gọi hàm predict). Theo mã bên trên thì nó là tập tin model.pkl. Hai là các thông tin về các gối thư viện (dependency) kèm theo để có thể chạy được model. Để chạy được model này chúng ta có thể dùng conda để chạy. Hiển nhiên là tìm hiểu conda sẽ được viết riêng trong phần khác. Nó nhiều thứ để nói. Ở đây tôi đã hiểu conda :). Theo mã bên thì nó nằm trong các tập tin requirements.txt, conda.yaml và python_env.yaml. Ngoài 2 thành phần chính trong một artifact đã nói bên trên còn có nhiều tập tin các kèm theo nếu một ghi lại để tiện cho theo dõi, đánh giá kết quả huấn luyện sau này. Đó là thứ mà tôi muốn nói trong bài viết này. Tạo biểu đồ hình ảnh thông qua thư viện Matplotlib và Seaborn.Tôi thấy có lớn hơn 2 thư viện dùng trong vẽ các biểu đồ trong máy học. Nhưng tìm kiếm thì thấy matplotlib và seaborn dùng nhiều. Nó gần như là công cụ bắt buộc khi chúng ta tiếp cận đến máy học, khoa học dữ liệu, phân tích dữ liệu và kỹ sư dữ liệu đôi khi cũng cần nó. Cài đặt nó dễ dàng. Ai biết Python cũng sẽ biết làm thế nào cài đặt một thư viện mới trong môi trường ảo Python. Dưới đây là một ví dụ vẽ biểu đồ đường trong seaborn sau đó suất ra ảnh png. 123456789101112...import matplotlib.plot as pltimport seaborn as sns......fig = plt.figure()sns.lineplot(data=[[1, 2, 3, 4, 5, 6], [10, 5, 12, 3, 5, 6, 7]])plt.axhline(5, linestyle='dotted', c='red')plt.savefig('./linechart.png')plt.close()... Đoạn mã trên dùng cả matplotlib lẫn seaborn. Nhưng để ý một xí chúng ta không thấy nó liên quan 2 thư viện đó mới nhau đúng đúng không? Một lệnh quan tâm nhất làm plt.savefig(...) mà trong khi đó sns.lineplot(...) vẽ biểu đồ nó không được gán vào trong plt. Nó lấy được biểu đồ trong seaborn vì nó là kế thừa thư viện matplotlib và dùng thư viện đó dưới dạng toàn cục thì phải. Có vài bài nói về vụ này như tôi chưa tìm hiểu thử. Cuối cùng dòng lệnh bên trên sẽ xuất ra một tấm hình png đặt cùng thư mục với tập tin Python mà ta đã chạy. Một biểu đồ đường trên trục xy và một đường đứt khúc gạch ngang vị trí giá trị 5 trên trục y và song son với trục x. Nhưng mục tiêu chính của bài này là kết hợp MLFlow và các thư viện Seanborn, Matplotlib để tạo ra hình ảnh biểu đồ sau đó lưu nó vào trong một artifact. Matplotlib, Seaborn tạo biểu đồ sau đó lưu vào artifact của MLFlow.Biểu đồ được tạo ra dưới dạng một Figure (có thể đó là một đối tượng của matplotlib sinh ra dành cho hình ảnh). Ta có thể vẽ thêm những đối tượng khác (đường thẳng hay một biểu đồ khác trong hình ảnh này. Chắc nó giống một tờ giấy trắng muốn vẽ gì vẽ lên đó). Trong đoạn mã bên dưới seaborn vẽ một biểu đồ đường rồi sau đó matplotlib vẽ thêm một đường ngang với định dạng đứt khúc. Chúng chồng lên nhau trong một tờ giấy trắng figure. 12345...fig = plt.figure()sns.lineplot(data=[[1, 2, 3, 4, 5, 6], [10, 5, 12, 3, 5, 6, 7]])plt.axhline(5, linestyle='dotted', c='red')... Đã nói quá dài dòng nhưng cuối cùng chỉ cần một lệnh trong MFLow đã có thể lưu một biểu đồ hình ảnh vào artifact rồi. 123456789...import matplotlib.plot as pltimport mlflow...fig = plt.Figure()...mlflow.log_figure(fig, 'tracking.png')... Và bây giờ để vào trong website tracking của MLFlow xem trong artifact có một tập tin tên tracking.png không? Chắc chắn là có vì tôi đã thử rồi mà. Còn mlflow tracking website là gì thì phải đọc thêm trong MLFlow thôi. MLflow Tracking &mdash; MLflow 1.26.1 documentation Đơn giản để sử dụngNói dài dòng để có thể diễn nghĩa thêm nhằm hạn chế những gì còn thiếu và tạo điều kiện để mở rộng. Nhưng nội dung bài viết chỉ được một tả đơn giản. Sử dụng thư viện matplotlib và seaborn để vẽ biểu đồ và chứa nó trong một đối tượng Feature của matplotlib. Sau đó dùng log_figure để viết hình ảnh đó thành mộ tập tin dưới dạng hình ảnh png trong thư mục artifact.","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"},{"name":"Sử dụng","slug":"Su-dung","permalink":"http://nguyenvantien2009.com/categories/Su-dung/"}],"tags":[{"name":"mlflow","slug":"mlflow","permalink":"http://nguyenvantien2009.com/tags/mlflow/"},{"name":"mlflow-tracking","slug":"mlflow-tracking","permalink":"http://nguyenvantien2009.com/tags/mlflow-tracking/"},{"name":"mlflow-visualization","slug":"mlflow-visualization","permalink":"http://nguyenvantien2009.com/tags/mlflow-visualization/"},{"name":"seaborn-matplotlib","slug":"seaborn-matplotlib","permalink":"http://nguyenvantien2009.com/tags/seaborn-matplotlib/"},{"name":"mlops","slug":"mlops","permalink":"http://nguyenvantien2009.com/tags/mlops/"}],"author":"nguyenvantien2009"},{"title":"Không Tạo Các Tập Tin Sao Lưu Và Phục Hồi Trong Thư Mục Hiện Tại Khi Dùng Vim để Soạn Thảo.","slug":"2022/khong-tao-cac-tap-tin-sao-luu-va-phuc-hoi-trong-thu-muc-hien-tai-khi-dung-vim-de-soan-thao","date":"2022-06-03T17:00:00.000Z","updated":"2022-07-30T17:15:39.414Z","comments":true,"path":"2022/khong-tao-cac-tap-tin-sao-luu-va-phuc-hoi-trong-thu-muc-hien-tai-khi-dung-vim-de-soan-thao.html","link":"","permalink":"http://nguyenvantien2009.com/2022/khong-tao-cac-tap-tin-sao-luu-va-phuc-hoi-trong-thu-muc-hien-tai-khi-dung-vim-de-soan-thao.html","excerpt":"","text":"Không tạo các tập tin sao lưu và phục hồi trong thư mục hiện tại khi dùng Vim để soạn thảo.Mình rất thích dùng Vim để soạn thảo vài dòng mã nguồn đơn giản. Nó được thực thi bằng dòng lệnh (command line) trên mà hình trắng đen kiểu dòng lệnh hay thấy (Console). Nó làm tôi cảm thấy rất nhanh và có gì đó chuyên nghiệp. Tuy nhiên khi tôi cài đặt và sử dụng Vim trong Window tôi gặp các tập tin không cần thiết (không cần thiết với tôi nhưng cần thiết với máy tính thì phải). Các tập tin có phần đuôi ~ và .un~. Nó làm tôi phiền phức khi thực hiện lệnh commit trong các dịch vụ source control như SVN hay Git. Do đó tôi không muốn thấy nó trong thư mục đang làm việc của mình. Để làm điều này không đơn giản nếu bạn chưa biết. Tôi đã tốn gần 1/2 ngày để tìm và thử. Và không muốn mình quên trong tương lai nên đã viết bài này để lưu lại sau này. Nó thuộc dạng thiết lập một lần sài mãi mãi nếu mình không đổi máy tính nên sẽ ít gặp và gặp rồi dễ quên. Hình ảnh là bài viết được soạn thảo sau đó xuất bản trên Hexo. Thiết lập cấu hình cho VimKhi cài thành công Vim trong máy tính thì chúng ta sẽ có một tập tin để thiết lập các thông số khởi chạy nó. Tên và đường dẫn của nó cũng sẽ khác nhau phụ thuộc vào hệ đều hành và cách thức cài đặt. Tôi dùng Window nên tôi sẽ viết bài này trên Windown. Trong Window tập tin thiết lập các thông số đó có tên là _vimrc không có đuôi mở rộng nào (không có phần .dochay đại loại thế). Nó được đặt trong thư gốc của Vim mà bạn đã cài đặt (đường dẫn nó bạn tự tìm nha thường nằm trong Program Files…). Thiết lập cần thiết để không dùng các tập tin dạng sao lưu và phục hồi.Thiết lập các thông số là phần chính của bài viết sau khi bạn đã mở được tập tin cấu hình (bài viết trong Window). 1234set nobackup # set no run backup (not create file subfix ~)set writebackup set noswapfile # set no swapfileset noundofile # set no run undo file (not create file subfix .un~) Khối lệnh trên có thể đặt ở dòng thứ 3 hay 4 gì đó trong tập tin cũng được. Nhớ lưu nó lại và quay về giao diện dòng lệnh để mở tập tin với vim thay đổi nội dung nào đó trong tập tin. Mở thư mục cùng nơi mà tập tin đang được chỉnh sửa để kiểm tra xem có tạo mấy tập tin đó không. Và tôi chắc là bạn không còn thấy chúng nữa nếu làm đúng từ đầu đến giờ. Thiết lập để đưa các tập tin sao lưu và phục hồi đến một thư mục khác.Làm đến đây là OK rồi. Nhưng chúng ta cũng dễ dàng đoán được Vim không rãnh ran để tạo các tập tin đó. Chúng được tạo ra để thuận tiện cho sao lưu và phục hồi khi ta có gì đó sai trong quá trình soạn thảo. Nếu bỏ nó đi thì cũng có thể sẽ không an toàn với chúng ta nhưng nếu để lại thì quá phiền phức khi nó không tự xóa đi khi chúng ta soạn thảo xong. Trong cách thiết lập của Vim cũng có cho cấu hình đường dẫn các tập tin đó đến một nơi khác. Điều này giúp chúng ta sửa nội dung các tập tin an toàn hơn. Hạn để mất mát vì một bản sao lưu đã được đưa vào một thư mục khác. Dưới đây là cách cấu hình đường dẫn 3 hành vi thường được xãy ra khi mở soạn thảo nội dung của một tập tin. 123set backupdir=~/.vim/backup//,.set undodir=~/.vim/undo//,.set directory=~/.vim/tmp//, Lưu ý: trong dòng lệnh bên trên ~ nó có ý nghĩa là đường dẫn đến thư mục profile của tài khoản mà chúng ta đang sử dụng trên Window. Nếu bạn đang dùng tài khoản tien.nguyen thì bạn sẽ có thư mục C:\\Users\\tien.nguyen. 3 dòng lệnh trên sẽ được thay thế bởi các thông số đã được thiết lập ở phần 2 của bài viết (cụ thể là có thể nằm ở vị trí dòng thứ 3 của tập tin). Nó tương ứng với 3 hành động sao lưu, phục hồi và lưu tạp các thông tin của tập mà ta đang soạn thảo. Cũng giống như phần 2. Ta phải lưu tập tin và thử lại với lệnh vim để thấy kết quả. Tài liệu tham khảo Tài liệu hướng dẫn về Vim https://riptutorial.com/vim","categories":[{"name":"Thủ thuật","slug":"Thu-thuat","permalink":"http://nguyenvantien2009.com/categories/Thu-thuat/"}],"tags":[{"name":"Vim","slug":"Vim","permalink":"http://nguyenvantien2009.com/tags/Vim/"},{"name":"Console","slug":"Console","permalink":"http://nguyenvantien2009.com/tags/Console/"}],"author":"Tien Nguyen"},{"title":"Setup a NodeJS Project With Typescript","slug":"2021/setup-a-nodejs-project-with-typescript","date":"2021-02-13T07:59:00.000Z","updated":"2022-06-02T08:53:17.081Z","comments":true,"path":"2021/setup-a-nodejs-project-with-typescript.html","link":"","permalink":"http://nguyenvantien2009.com/2021/setup-a-nodejs-project-with-typescript.html","excerpt":"","text":"How to setup a NodeJS project with TypescriptThere are already many perfect articles on this topic so I won’t need to create a new post on a popular topic. But I also created this theme to add links that I think are perfect for your convenience and for you without further searching. I’ll list out the basic steps I’ve seen in the links below to remind me next time. If the installation is required you need to go to the details of a link to follow. Source from Github https://github.com/nguyenvantien2009/typescript-express-starter I will usually update new version so you see different between content of post and git version. Step 1: Create a project by NPM with npm init. Step 2: Install dependences as in dev typescript, tslint, @types/express. In product express. Step 3: Configuring Typescript tsconfig.json – config build project –, tslint.json – config syntax –. Use 2 command lines tsc --init and ./node_modules/.bin/tslint --init. Link tsconfig / Link tslink. Step 4: Edit package.json to run typescript in script property. Then run by npm start. Link And here are links: How To Set Up a Node Project With Typescript. Date: 2021-02-13 - https://www.digitalocean.com/community/tutorials/setting-up-a-node-project-with-typescript How to set up a TypeScript project. Date: 2021-02-13 - https://www.freecodecamp.org/news/how-to-set-up-a-typescript-project-67b427114884/ Creating A Typescript Project. Date: 2021-02-13 - https://dev.to/creepinson/creating-a-typescript-project-47gl Above are the links I have followed and make sure it worked - not sure if the link is still alive at the time you visit. But if you follow and still cannot run or do not know where the error is to fix it, you can ask me by email if needed. Referencestsconfig.json file1234567891011{ "compilerOptions": { "module": "commonjs", "esModuleInterop": true, "target": "es6", "moduleResolution": "node", "sourceMap": true, "outDir": "dist" }, "lib": ["es2015"]} tslint.json file123456789{ "defaultSeverity": "error", "extends": ["tslint:recommended"], "jsRules": {}, "rules": { "no-console": false }, "rulesDirectory": []} package.json file1234567891011121314151617181920{ "name": "node-with-ts", "version": "1.0.0", "description": "", "main": "dist/app.js", "scripts": { "start": "tsc && node dist/app.js", "test": "echo \\"Error: no test specified\\" && exit 1" }, "author": "", "license": "ISC", "devDependencies": { "@types/express": "^4.16.1", "tslint": "^5.12.1", "typescript": "^3.3.3" }, "dependencies": { "express": "^4.16.4" }}","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"NodeJS","slug":"NodeJS","permalink":"http://nguyenvantien2009.com/tags/NodeJS/"},{"name":"Typescript","slug":"Typescript","permalink":"http://nguyenvantien2009.com/tags/Typescript/"},{"name":"How","slug":"How","permalink":"http://nguyenvantien2009.com/tags/How/"},{"name":"Setup","slug":"Setup","permalink":"http://nguyenvantien2009.com/tags/Setup/"}],"author":"Tien Nguyen"},{"title":"Use Odoo XML-RPC to Build Applications Customization in Windows and Mobile.","slug":"2021/use-odoo-xml-rpc-to-build-applications-customization-in-windows-and-mobile","date":"2021-02-12T17:00:00.000Z","updated":"2022-06-02T09:03:13.661Z","comments":true,"path":"2021/use-odoo-xml-rpc-to-build-applications-customization-in-windows-and-mobile.html","link":"","permalink":"http://nguyenvantien2009.com/2021/use-odoo-xml-rpc-to-build-applications-customization-in-windows-and-mobile.html","excerpt":"","text":"USE ODOO XML-RPC TO BUILD APPLICATIONS CUSTOMIZATION IN WINDOWS AND MOBILE. Odoo is a well-designed ERP (Enterprise Resource Planning). So we can confidently build plugins or applications that reuse data from Odoo. Luckily, Odoo provided XML-RPC. It is a Remote Procedure Call protocol with XML data format. In this post, we use XML-RPC by NodeJS to build a Result API to provide web app and mobile app. Using XML-RPC in OdooXML-RPC already exists by default in Odoo. We don’t need to enable or disable it, we just need to have the account login as login form web application. XML-RPC is better HTTP Request because it integrate directly with ERP Server without ERP Web Client. To integrate Odoo, we use odoo-xmlrpc module in npm. It allow call with method list, read, insert, update and delete as other CRUD. The odoo-xmlrpc have 4 functions to call to XML-RPC Odoo. 1234odoo.connect(callback) // use login accountodoo.execute_kw(model,method,params,callback) // call CRUD method.odoo.exec_workflow(model,method,params,callback)odoo.render_report(report,params,callback) You need refer to https://www.npmjs.com/package/odoo-xmlrpc to see more usage guides. Create a Restful API to call XML-RPCRPC is difficult protocol to use so I need create Restful API for other applications as web app and mobile app. I like use NodeJS to build API. In this post, I use a Odoo-XMLRPC. Source in Github https://github.com/nguyenvantien2009/odoo-xmlrpc-rest.git. We need modules in project as express (build Restful service), body-parser (parse JSON format in request body), cors (help cross-domain handler). 1npm i express body-parser cors morgan --save To list all modules (dependences) of project, you need call npm ls command line. Base on that we can remove some modules no need to increase size of node-modules folder. I also you need refer to http://expressjs.com/en/resources/middleware[^3], if need add middle modules for each request Build Web Application call Restful APIBuild Mobile Application call Restful APIPerformance evaluation and development performanceConclusion and development capabilitiesReferences[^1]: XML-RPC for Odoo in Node JS - https://www.npmjs.com/package/odoo-xmlrpc[^2]: Sample code for Odoo-XMLRPC - https://github.com/nguyenvantien2009/odoo-xmlrpc-rest.git[^3]: Express middleware - http://expressjs.com/en/resources/middleware","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Odoo","slug":"Odoo","permalink":"http://nguyenvantien2009.com/tags/Odoo/"},{"name":"ERP","slug":"ERP","permalink":"http://nguyenvantien2009.com/tags/ERP/"},{"name":"XML-RPC","slug":"XML-RPC","permalink":"http://nguyenvantien2009.com/tags/XML-RPC/"},{"name":"Odoo API","slug":"Odoo-API","permalink":"http://nguyenvantien2009.com/tags/Odoo-API/"}],"author":"Tien Nguyen"},{"title":"Build Icon Font From SVG","slug":"2021/build-icon-font-from-svg","date":"2021-02-09T17:00:00.000Z","updated":"2022-06-02T08:30:19.930Z","comments":true,"path":"2021/build-icon-font-from-svg.html","link":"","permalink":"http://nguyenvantien2009.com/2021/build-icon-font-from-svg.html","excerpt":"","text":"Build Icon Font from SVG The Icon is an dispensable component web applications and even on advertising websites. We can use PNG, JPG as icon image but there will be image resolution issues. Therefore SVG is a good choice. It can render on page load so it’s up to the browser to render the best possible images. If using images as an icon then there are some inconvenience problems with integrating them all into CSS file and use it as font-family. There are also many free packages available that include font icons. But if we need customization it takes a few steps and requires the assistance of a few tools. This post I will help you do that easily through [IcoMoon][]. Note: You already have basic knowledge of web programming. The concept of HTML, CSS and SVG images have been approached before. [IcoMoon]: https://icomoon.io/ “Ico Moon - Help convert image to Icon Font.” Download SVG IconYou can find SVG image in Internet but pay attention to copyright. I find out a website that could positive provide them [iconmonstr][]. There are many free icons in SVG image format. Please download the list of icons you need. We use them to create fonts with [IcoMoon][]. [iconmonstr]: https://iconmonstr.com/ “Ion Mon Str” Convert SVG to Font Style[IcoMoon][] is online service help to convert SVGs to fonts. In addition, it also converts many other types of images. To convert the SVGs image to font it will merge the SVG images into a default file with name is icommon.svg. Besides, it also generates .eot, .ttf, .woff files. these files will be appended in the style.css file with the font-family property. Upload SVGs to [IcoMoon][]. Select image list then click Generate Font button in the footer. Unzip after download success. Copy fonts folder and style.css file to project. Add style link in main page (maybe index.html). And below are the detailed explanations each step: Step 1: Access to [IcoMoon][] choose project or create new project to upload SVGs. Step 2: In here have a lot of free icons. You can select multi collection (icon sets) generate to font. Click to choose/un-choose (same Window OS). Then click Generate Font at the footer of page to download package that [IcoMoon][] generated. Step 3: Unzip package that was downloaded in Step 2. Then copy 2 things: (1) fonts folder. (2) style.css to CSS folder of project. Note: fonts and style.css must put same the folder. Step 4: Add link to style.css file into master page or index.html in the project as other CSS links. Finally, we need add class to tag that need show as icon with prefix is icon_. E.gs: Show icon home in div tag. <div class='icon-home'></div>. Additional description: This is a part of style.css. (IcoMoon generate style.css file). 123456789101112131415161718192021222324252627282930@font-face { font-family: 'icomoon'; src: url('fonts/icomoon.eot?7vzdwv'); src: url('fonts/icomoon.eot?7vzdwv#iefix') format('embedded-opentype'), url('fonts/icomoon.ttf?7vzdwv') format('truetype'), url('fonts/icomoon.woff?7vzdwv') format('woff'), url('fonts/icomoon.svg?7vzdwv#icomoon') format('svg'); font-weight: normal; font-style: normal; font-display: block;}[class^="icon-"], [class*=" icon-"] { /* use !important to prevent issues with browser extensions that change fonts */ font-family: 'icomoon' !important; speak: never; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; line-height: 1; /* Better Font Rendering =========== */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;}.icon-amazon:before { content: "\\e900";} [IcoMoon][] also generate fonts, it contain files font format as .ttf, .woff, .eot. One of the important format is woff (Web Open Font Format). It was used since 2010 by Mozilla Foundation for web. This is link help you refer. References[^1]: IcoMoon Site - Generate from SVGs to Font Service.[^2]: IconMonStr - Provide free icon SVGs.","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Icon","slug":"Icon","permalink":"http://nguyenvantien2009.com/tags/Icon/"},{"name":"Font Style","slug":"Font-Style","permalink":"http://nguyenvantien2009.com/tags/Font-Style/"}],"author":"Tien Nguyen"},{"title":"PoS Machine Brands Are Being Used Popularly in Vietnam","slug":"2021/pos-machine-brands-are-being-used-popularly-in-vietnam","date":"2021-02-09T17:00:00.000Z","updated":"2022-06-02T08:52:50.365Z","comments":true,"path":"2021/pos-machine-brands-are-being-used-popularly-in-vietnam.html","link":"","permalink":"http://nguyenvantien2009.com/2021/pos-machine-brands-are-being-used-popularly-in-vietnam.html","excerpt":"","text":"PoS Machine Brands Are Being Used Popularly In Vietnam Brand List CitiZen Denso Epson Posiflex Samsung References[PoS machine brands list used in Vietnam]: https://dinhthien.com.vn/giai-phap/he-thong-ban-hang/cac-thuong-hieu-may-pos-tinh-tien-tai-viet-nam “PoS machine brands used in Vietnam.”","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"PoS","slug":"PoS","permalink":"http://nguyenvantien2009.com/tags/PoS/"},{"name":"Printer","slug":"Printer","permalink":"http://nguyenvantien2009.com/tags/Printer/"}],"author":"Tien Nguyen"},{"title":"Establish a Wireless Connection for the Raspberry Pi","slug":"2021/establish-a-wireless-connection-for-the-raspberry-pi","date":"2021-02-08T17:00:00.000Z","updated":"2022-06-02T08:35:39.513Z","comments":true,"path":"2021/establish-a-wireless-connection-for-the-raspberry-pi.html","link":"","permalink":"http://nguyenvantien2009.com/2021/establish-a-wireless-connection-for-the-raspberry-pi.html","excerpt":"","text":"Establish a wireless connection for the Raspberry Pi Install RaspberryInstalling the Raspbian operating system is obvious before setting up a wireless connection. Since the installation of the Raspbian operating system is quiet long, it will be covered in the post with links Install Raspbian OS in Raspberry Pi. Setting connect wireless with monitorIf we have a monitor connect to Raspberry we would be more convenient to manipulate. We no need use SSH to control from machine. Below are the instructions to connect wireless to Raspbian. Config wireless connect by Raspbian OS Lite.Raspbian Lite is light operation system of Raspbian. It don’t have a graphical interface but only interactive graphics in the form of a console. It is commonly used in IoT applications because it is lightweight and can be less energy consuming than a full operating system. When start Raspbian OS. If the system ask username and password to login. We can try with username is pi and password raspberry. But still can not login, maybe default account be changed so should search in Google. I think we don’t need much description for this setup because when type raspi-config, we easily see all the options for being able to establish a wireless connection. Notes: We also need enable SSH of Raspbian in options show in monitor. It is also easy to find and setting up. Config wireless connect by Command Line. Check wireless available in Raspbian sudo iwlist wlan0 scan? Add config file wpa_supplicant.conf in /boot. Edit contain of config file wpa_supplicant.conf. Reload config to read and connect wireless by sudo wpa_cli -i wlan0 reconfigure. And here are the detailed explanations of the steps: Step 1: We need a monitor and keyboard is connected to Raspberry before start Raspbian OS. In the Raspberry, scan wireless which it can see by sudo iwlist wlan0 scan command line. That command line, we see SSID of wireless to use for Step 2 or Step 3. Step 2: Insert SD Card with installed Raspbian OS than add wpa_supplicant.conf file to /root. This file will be loaded into folder /etc/wpa_supplicant/wpa_supplicant.conf Raspbian is first booted in device. The content of the file is mentioned in wpa_supplicant.config Step 3: (Optional) If you set config wireless connection in Step 2, we can skip this step. But we also can change config after it be loaded in Raspbian. If need change config in wpa_supplicant.conf file, need use nano /etc/wpa_supplicant/wpa_supplicant.conf and refer to contain of wpa_supplicant.config. Step 4: (Optional) If we change config in Step 3, we need reload network configuration. Let try sudo wpa_cli -i wlan0 reconfigure to reload configuration. Setting connect wireless without monitor or keyboardIf you don’t have monitor and keyboard, we can not choose options by monitor and keyboard. So we must use choose Config wireless connect by Command Line. Fileswpa_supplicant.conf1234567ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdevupdate_config=1country=<Insert 2 letter ISO 3166-1 country code here>network={ ssid="<Name of your wireless LAN>" psk="<Password for your wireless LAN>"} SSID is name of your wireless LAN. [SSID Detection][] psk is password for your wireless LAN. Pictures Edit config network in Raspberry Reload network config. References Setting up a Raspberry Pi headless from Raspberry Raspi-Config command line Setting up a wireless LAN via the command line Cài đặt Wifi trên Raspberry bằng wpa_supplicant.conf [^1]: SSID is short for Service Set Identifier. [SSID Detection][] [SSID Detection]: https://support.brother.com/g/b/faqend.aspx?c=vn&lang=en&prod=p750weas&faqid=faqp00100049_000 “How to get SSID of wireless”","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"Rasberry Pi","slug":"Rasberry-Pi","permalink":"http://nguyenvantien2009.com/tags/Rasberry-Pi/"},{"name":"Wireless","slug":"Wireless","permalink":"http://nguyenvantien2009.com/tags/Wireless/"},{"name":"Wireless Raspberry Pi","slug":"Wireless-Raspberry-Pi","permalink":"http://nguyenvantien2009.com/tags/Wireless-Raspberry-Pi/"}],"author":"Tien Nguyen"},{"title":"Setup X-Printer Connection to Print Receipt HTML Format","slug":"2021/setup-xprinter-connection-to-print-receipt-html-format","date":"2021-01-24T17:00:00.000Z","updated":"2022-06-02T08:54:17.224Z","comments":true,"path":"2021/setup-xprinter-connection-to-print-receipt-html-format.html","link":"","permalink":"http://nguyenvantien2009.com/2021/setup-xprinter-connection-to-print-receipt-html-format.html","excerpt":"","text":"Setup X-Printer Connection To Print Receipt HTML Format Payment slip printing is an inevitable requirement of retail cashier applications. But to support many different types of printers is a problem for programmers. For high cost printers, the good support of protocols helps the programmer work less. But if you need to support printers from China, you need more skills. Setup Driver X-Printer which provide by X-Printer[^1]Using any device need to install the driver provided by the device vendor. The X-Printer is no exception. First, download and install the necessary driver from the vendor corresponding to the printer model you are using. Here is the path where you can download list of drivers. To install the required driver and setup I have a more detailed article mentioned in Installing driver for X-Printer. For programmers, please pay attention to add the X-Printer SDK provided in X-Printer SDK. Here you can download the necessary source code libraries for each platform and operating system. We’ll definitely use the printer use case in conjunction with the built-in Android PoS app including the printer. Setup Zadig To Convert USB ConnectionZadig is a Windows application that helps to install generic USB drivers such as WinUSB, [libusbK][4], [libusb-win32][libusb-win32]. After installing the shared driver, we should see the printer which connected. Please refer to Install Zadig to convert USB driver for printer. If you do not see a device on the list you need to go to Device (top menu) to find the device. Then select the Driver that you think is the driver from the printer to click the Replace Driver button. After the installation is complete you will receive a notification that the installation was successful. So we can start writing the source code to connect the printer. Setup Script Connect and Print in NodeJSIn this article I used NodeJS to connect to a printer and print a receipt. The library used is escpos in npm. 1npm install escpos After installing the library we need to write a script to be able to connect to the printer and print. 123456789101112131415161718192021222324252627282930313233343536const escpos = require('escpos');// install escpos-usb adapter module manuallyescpos.USB = require('escpos-usb');// Select the adapter based on your printer typeconst device = new escpos.USB();// const device = new escpos.Network('localhost');// const device = new escpos.Serial('/dev/usb/lp0'); const options = { encoding: "GB18030" /* default */ }// encoding is optional const printer = new escpos.Printer(device, options); device.open(function(error){ printer .font('a') .align('ct') .style('bu') .size(1, 1) .text('The quick brown fox jumps over the lazy dog') .text('Máy in từ Nguyễn Văn Tiển.', 'windows1251') .text('敏捷的棕色狐狸跳过懒狗') .barcode('1234567', 'EAN8') .table(["One", "Two", "Three"]) .tableCustom( [ { text:"Left", align:"LEFT", width:0.33, style: 'B' }, { text:"Center", align:"CENTER", width:0.33}, { text:"Right", align:"RIGHT", width:0.33 } ], { encoding: 'cp857', size: [1, 1] } // Optional ).qrimage('https://github.com/song940/node-escpos', function(err){ this.cut(); this.close(); });}); The printer is now connected to the computer via a USB port. So we can run the above code with NodeJS to print it out. Although it was printed out but there are some font problems in Vietnamese although I have found and tested encodes in library iconv-lite [^ 2] but still no result. References[1]: https://xprinter.vn/download-driver-may-in-driver-pos-printer/ “X-Printer Vietnam Driver”[2]: https://www.xprintertech.com/ “X-Printer Technology from China”[3]: https://sourceforge.net/projects/libwdi/files/zadig/ “Zadig for Window”[4]: http://libusbk.sourceforge.net/UsbK3/ “libusbK”[libusb-win32]: https://sourceforge.net/p/libusb-win32/wiki/Home/ “libusb-win32 is a port of libusb” [^2]: iconv-lite is a library in NodeJS help encode for printer. https://www.npmjs.com/package/iconv-lite[^1]: X-Printer is a brand from China.","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"PoS","slug":"PoS","permalink":"http://nguyenvantien2009.com/tags/PoS/"},{"name":"X-Printer","slug":"X-Printer","permalink":"http://nguyenvantien2009.com/tags/X-Printer/"},{"name":"Print Receipt","slug":"Print-Receipt","permalink":"http://nguyenvantien2009.com/tags/Print-Receipt/"},{"name":"Hardware","slug":"Hardware","permalink":"http://nguyenvantien2009.com/tags/Hardware/"}],"author":"Tien Nguyen"},{"title":"Install MinIO for Storage Cloud","slug":"2021/install-minio-docker","date":"2021-01-16T17:00:00.000Z","updated":"2022-06-02T08:47:56.225Z","comments":true,"path":"2021/install-minio-docker.html","link":"","permalink":"http://nguyenvantien2009.com/2021/install-minio-docker.html","excerpt":"","text":"Install Storage Cloud with MinIO Source for InstallThis is yaml script docker-compose.yml to install MinIO. 123456789101112version: '3.7'services: minio: image: minio/minio ports: - "9000:9000" volumes: - ./storage/minio:/data environment: MINIO_ACCESS_KEY: minio_access_key MINIO_SECRET_KEY: minio_secret_key command: server --address 0.0.0.0:9000 /data Let enable port to run MinIO if the firewall has disabled is default setting. Run command ufw allow 9000. Now we need access with URL http://localhost:9000 (localhost is IP address which install MinIO). However, when use MinIO in production environment. Maybe we will need docker swarm or Kubernetes. So we need create a docker-compose. References MinIO Documents","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"MinIO - Storage Cloud","slug":"MinIO-Storage-Cloud","permalink":"http://nguyenvantien2009.com/tags/MinIO-Storage-Cloud/"}],"author":"Tien Nguyen"},{"title":"Setup Development for Odoo","slug":"2021/setup-development-evironment-for-odoo","date":"2020-12-12T17:00:00.000Z","updated":"2022-06-02T08:53:31.690Z","comments":true,"path":"2021/setup-development-evironment-for-odoo.html","link":"","permalink":"http://nguyenvantien2009.com/2021/setup-development-evironment-for-odoo.html","excerpt":"","text":"Often developers develop a plugin they need the necessary steps to set up the preparation environment for development. Besides, software deployers need to visualize the steps they take to deploy the product. Install Odoo by DockerWe use docker-compose for ease of installation. To launch the Odoo application we need a database and web. In docker-compose will include 2 containers of these. It is installed automatically when running the command docker-compose up. 12345678910111213141516version: '2'services: web: image: odoo:14.0 depends_on: - db ports: - "8069:8069" volumes: - ./addons:/mnt/extra-addons db: image: postgres:10 environment: - POSTGRES_DB=postgres - POSTGRES_PASSWORD=odoo - POSTGRES_USER=odoo Here we use volumes to link the /mnt/extra-addons directory in Odoo. Here the plugin will be developed and added to install in the Odoo Install Backend. Develop PluginHow to develop a plugin you need to refer to the documentation for the Odoo versions. In this post I mention Odoo 14. It is also compatible from Odoo 10 and above. 1. Enable Odoo’s development modeFirst we need to change Odoo’s mode to development mode. To do that, we need to install at least 1 module from the apps (I have sale installed). Then access to Setting -> Setting General. You search for Deactivate developer mode and click to turn on developer mode. 2. Create a plugin structureThe ultimate goal is to create the directory and file structure of a plugin. We can create with a manual follow-up document from Odoo [3]. For another method we use odoo-bin. It is Odoo’s command line for using module creation, server on / off … In this post, I use odoo-bin to create the structure of the module. I need to download odoo-bin. It’s in the odoo source in Github. And the command line to run is py odoo-bin ... or python odoo-bin ... is the dependency on python installed in your PC. Install modules are required to use odoo-bin. 12pip3 install setuptools wheelpip3 install -r requirements.txt After successful installation. I can use odoo-bin create new a plugin. 1py odoo-bin scaffold ${module name} ${where to put it} Then check in ${where to put it} you will see folder contain most of the neccessary files and folders. Install and Reload PluginTo install new module, go to App in top menu. Search name of module which you install. Then click install button to sucess. If your module have setting menu on top menu (root menu), we can go to header menu to access this module. In development process, we will change code and test. After change code we need go back App menu and search name of module to click Upgrade. Upload Plugin to Odd AppReferences Install Odoo SaaS by Docker Activate the Developer (Debug) Mode in Odoo Building a Module in Odoo","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Odoo","slug":"Odoo","permalink":"http://nguyenvantien2009.com/tags/Odoo/"},{"name":"Install Odoo","slug":"Install-Odoo","permalink":"http://nguyenvantien2009.com/tags/Install-Odoo/"}],"author":"Tien Nguyen"},{"title":"How to Change Password Admin for Wordpress?","slug":"2021/how-to-change-password-admin-for-wordpress","date":"2020-11-16T17:00:00.000Z","updated":"2022-06-02T08:47:43.503Z","comments":true,"path":"2021/how-to-change-password-admin-for-wordpress.html","link":"","permalink":"http://nguyenvantien2009.com/2021/how-to-change-password-admin-for-wordpress.html","excerpt":"","text":"Note: wp_ is prefix of tables in wordpress. You can change in wp_config.php file We need 2 steps to change passowrd for administrator in wordpress.Step 1: Update user_pass column in wp_user table.Step 2: Insert or update wp_capabilities and wp_user_level in wp_usermeta table. Step 1: Update user_pass column in wp_user table.SQL Command help to update. 12345678910INSERT INTO `wp_users` ( `ID`, `user_login`, `user_pass`, `user_nicename`, `user_email`, `user_url`, `user_registered`, `user_activation_key`, `user_status`, `display_name`) VALUES ( '4', 'dev', MD5('dev'), 'Your Name', 'test@vtsspace.com', 'http://vtsspace.com/', '2020-11-17 00:00:00', '', '0', 'Tien Nguyen'); Step 2: Insert or update wp_capabilities and wp_user_level in wp_usermeta table.SQL Command help to add. (But we also update if key ?_capabilities and ?_user_level are existed. Note: In this SQL command, we use userId = 1. It is id of user admin in wp_user table. 12345INSERT INTO `wp_usermeta` (`umeta_id`, `user_id`, `meta_key`, `meta_value`) VALUES (NULL, '1', 'wp_capabilities', 'a:1:{s:13:"administrator";s:1:"1";}');INSERT INTO `wp_usermeta` (`umeta_id`, `user_id`, `meta_key`, `meta_value`) VALUES (NULL, '1', 'wp_user_level', '10'); ConcludeWe need 2 steps to update password for administrator. We use MD5 alogrithms to encrypt plain text of password then update information of use in usermeta table. Now you can access admin site /wp-admin to login with account dev/dev. Reference How to Change Your Password in WordPress (Beginner’s Guide)","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Wordpress","slug":"Wordpress","permalink":"http://nguyenvantien2009.com/tags/Wordpress/"},{"name":"Password","slug":"Password","permalink":"http://nguyenvantien2009.com/tags/Password/"},{"name":"Website","slug":"Website","permalink":"http://nguyenvantien2009.com/tags/Website/"}],"author":"Tien Nguyen"},{"title":"Build NGINX Proxy Docker","slug":"2021/build-nginx-proxy-docker","date":"2020-09-23T17:00:00.000Z","updated":"2020-09-23T17:00:00.000Z","comments":true,"path":"2021/build-nginx-proxy-docker.html","link":"","permalink":"http://nguyenvantien2009.com/2021/build-nginx-proxy-docker.html","excerpt":"When we deploy services base on micro-service architecture, each service will take a port in OS. But users don’t ports to access each of services. So we need proxy to point services base on URL request.","text":"When we deploy services base on micro-service architecture, each service will take a port in OS. But users don’t ports to access each of services. So we need proxy to point services base on URL request. NGINX ConfigIn current folder, create config folder contain nginx.conf file. In here we define server information and proxy. Location is prefix of URI to apply proxy_pass. Target URL will build is $proxy_pass + $location. We need note to / end of path and proxy_pass. In here http://application:3000/, http://business:3000/… with application, business are service name from docker-compose use the same network. 12345678910111213141516171819202122232425262728293031323334353637383940414243worker_processes 2;events { worker_connections 1024; }http { sendfile on; upstream docker-nginx { server nginx:80; } # use for all server proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; server { listen 80; client_max_body_size 0; chunked_transfer_encoding on; client_body_buffer_size 128k; proxy_connect_timeout 90; proxy_buffers 32 4k; location /app/ { proxy_pass http://application:3000/; proxy_redirect off; } location /business/ { proxy_pass http://business:3000/; proxy_redirect off; } location /product/ { proxy_pass http://product:3000/; proxy_redirect off; } }} DockerfileWith ./config/nginx.conf is nginx configuration that we create in NGINX Config. 123FROM nginx:alpineCOPY ./config/nginx.conf /etc/nginx/nginx.conf DeploymentWe use private registry to ship nginx proxy container. 123# in current folderdocker build -t registry.address.com/nginx-proxy:1009 .docker push registry.address.com/nginx-proxy:1009 In here: registry.address.com is private registry address. 1009 is tag of image. We use tag as version of image. Now we add service nginx proxy to docker-compose.yml to deploy. 12345678910111213...nginx: image: registry.address.com/nginx:1009 ports: - 8080:80 networks: - posems logging: driver: json-filenetworks: posems: external: true... In here: posems is network that is created with type is overlay. 8080:80: We expose port 8080 from 80 of container. Deploy use SwarmpitSwarmpit is UI use Docker Swarm. To use private docker registry we need add new registry. After login with username and password from registry. References","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"Docker","slug":"Docker","permalink":"http://nguyenvantien2009.com/tags/Docker/"},{"name":"NGINX","slug":"NGINX","permalink":"http://nguyenvantien2009.com/tags/NGINX/"},{"name":"NGINX Proxy","slug":"NGINX-Proxy","permalink":"http://nguyenvantien2009.com/tags/NGINX-Proxy/"},{"name":"Proxy","slug":"Proxy","permalink":"http://nguyenvantien2009.com/tags/Proxy/"}],"author":"Tien Nguyen"},{"title":"CD/CD With Jenkins and Docker","slug":"2021/ci-cd-with-jenkins-docker","date":"2020-09-12T17:00:00.000Z","updated":"2022-06-02T08:33:20.776Z","comments":true,"path":"2021/ci-cd-with-jenkins-docker.html","link":"","permalink":"http://nguyenvantien2009.com/2021/ci-cd-with-jenkins-docker.html","excerpt":"","text":"1. Install Jenkins by Docker 2. Network in Jenkins Docker 3. Create a CI/CD with Jenkins 3.1. Create container call runner 3.2. Connect container to Jenkins network 3.3. Use Open SSH to control runner 4. References If we build an application on micro-service architecture, the CI/CD is process is indispensable. In this post we use Jenkins as a tool for CI/CD process. Docker is the best solution to deploy micro-service now. But it’s difficult if we don’t know about its network. The creation, connection and disconnection are 3 main actions to the containers see together. Have 3 main parts which we use in this page: source control, jenkins and runner. With source control, git/ svn are common app. The Jenkins will bet installed by Docker. Finally, the runner is a place to execute command line that have writen in Jenkins. 1. Install Jenkins by DockerTo install Jenkins we should set memory >= 8G by JAVA_OPTS option. 1234docker run -p 9090:8080 --name=jenkins-master -d \\ --env JAVA_OPTS="-Xmx8192m" \\ --env JENKINS_OPTS=" --handlerCountMax=300" \\ jenkins/jenkins WARNING: When run this command line, we will see a token as password. Let copy and save it to use when access URL jenkins after install success. But if we is forget it, we can re-try with command line. 12# Access to jenkins container and generate new password admin.docker exec jenkins-master cat /var/jenkins_home/secrets/initialAdminPassword 2. Network in Jenkins DockerJenkins is used as a tool for trigger when commit code to SVN or GIT. When the source control have any changes, Jenkins remote to other server to execute command lines that is writen. So network is important factor for the node to see each other. In here, we use bridge type of network to do that. Need 3 steps to nodes can see togethers. 12345678# create bridge network. `net4ci` is network's name.docker network create --driver bridge net4ci# connect networkdocker network connect net4ci jenkins-master# disconnect networkdocker network disconnect bridge jenkins-master Now we can list containers in a network name. 12# list containers in `net4ci` networkdocker network inspect net4ci -f "{{json .Containers }}" 3. Create a CI/CD with JenkinsAs mentioned above, we need an other PC/Container as runner to execute command lines. So we need create new container then we install the necessary programs for the command lines that we have writen in Jenkins. 3.1. Create container call runnerWe use Ubuntu for runner container. 1234567# install and use ubuntu as runner.docker pull ubuntudocker run -it ubuntudocker ps -adocker ps -ldocker start ID-container 3.2. Connect container to Jenkins networkTo Jenkins can see runner, we need to connect to net4ci network. This is basic knowledge in Docker. 12# connect to net4ci networkdocker network connect net4ci funny_tesla 3.3. Use Open SSH to control runnerAccess runner container to install common commands as ping. 123docker run -i -t debianapt-get updateapt-get install iputils-ping Next OpenSSH is a program that we aim to be able to perform remotely. 1234sudo apt updatesudo apt install openssh-serversudo systemctl status sshsudo ufw allow ssh 4. References","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"CI/CD","slug":"CI-CD","permalink":"http://nguyenvantien2009.com/tags/CI-CD/"},{"name":"Jenkins","slug":"Jenkins","permalink":"http://nguyenvantien2009.com/tags/Jenkins/"},{"name":"Automatic","slug":"Automatic","permalink":"http://nguyenvantien2009.com/tags/Automatic/"}],"author":"Tien Nguyen"},{"title":"Deploy Private NPM Registry","slug":"2021/deploy-private-npm-registry","date":"2020-09-10T17:00:00.000Z","updated":"2022-06-02T08:35:26.187Z","comments":true,"path":"2021/deploy-private-npm-registry.html","link":"","permalink":"http://nguyenvantien2009.com/2021/deploy-private-npm-registry.html","excerpt":"","text":"1. Install Verdaccio 2. Build NPM module 3. Add/push to registry in client 4. Using 4.1 NPM Run 4.2 Docker Compose 5. References default registry npm build library version and add dependecy: manage version, esier to deploy, 1. Install VerdaccioDefault config need be created config.yaml in /docker-app/verdaccio/conf folder. 12345678910111213141516storage: ./storageauth: htpasswd: file: ./htpasswduplinks: npmjs: url: https://registry.npmjs.org/packages: '@*/*': access: $all publish: $authenticated proxy: npmjs '**': proxy: npmjslogs: - {type: stdout, format: pretty, level: http} If we need change config, we can reference to [https://verdaccio.org/docs/en/configuration.html#default-configuration]. 1234567V_PATH=/docker-app/verdaccio;docker run -it --rm --name verdaccio \\ -p 4873:4873 \\ -v $V_PATH/conf:/verdaccio/conf \\ -v $V_PATH/storage:/verdaccio/storage \\ -v $V_PATH/plugins:/verdaccio/plugins \\ verdaccio/verdaccio WARNING: Before run docker Verdaccio, we need add permission for folders with UserID is 10001 (default user in Verdaccio docker). Here are the default Verdaccio parameters: VERDACCIO_APPDIR: /opt/verdaccio the docker working directoryVERDACCIO_USER_NAME: verdaccio the system userVERDACCIO_USER_UID: 10001 the user id being used to apply folder permissionsVERDACCIO_PORT: 4873 the verdaccio portVERDACCIO_PROTOCOL: http the default http protocol 2. Build NPM moduleCreate new module with name need scopse value. E.g: @vts/business. This scope value will use to define registry URL when pull or push package to registry. E.g: package.json file in framework module. 123456789101112131415{ "name": "@vts/framework", "version": "1.0.3", "description": "VTS Service Framework is a project use MoleculerJS framework to build Micro-service architecture. In here we can use for Authentication, Common Popular...", "main": "index.js", "scripts": { "test": "echo \\"Error: no test specified\\" && exit 1" }, "repository": { "type": "git", "url": "http://gitlab.vtsspace.com/vts-service/library/framework.git" }, "author": "nguyenvantien2009@gmail.com", "license": "ISC"} 3. Add/push to registry in clientDefault registry URL of NPM is [https://registry.npmjs.org/]. When we install new package by npm install {module-name}, NPM will download this package from [https://registry.npmjs.org/] hub. To install package from private registry, we need add new URL. Now we add set registry URL with scopse vts then login with this scopse if want to publish module to registry. 12npm config set @vts:registry http://npm.vtsspace.com:4873npm login --registry=http://npm.vtsspace.com:4873 --scope=@vts Now we can publish this module to registry by command line. Then access to [http://npm.vtsspace.com:4873] to see result. 12# go to root folder of module.npm publish http://npm.vtsspace.com:4873 4. UsingNOTE: We need npm config set @vts:registry http://npm.vtsspace.com:4873 before install package with vts scopse. NPM will auto redirect to [http://npm.vtsspace.com:4873] to download package. 4.1 NPM Run1npm install @vts/business --save 4.2 Docker ComposeIn docker, you also need set registry URL before running npm install. 12RUN npm config set @vts:registry http://npm.vtsspace.com:4873RUN npm install 5. References Install Verdaccio by Docker Creating and publishing scoped public packages","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"Registry","slug":"Registry","permalink":"http://nguyenvantien2009.com/tags/Registry/"},{"name":"NPM","slug":"NPM","permalink":"http://nguyenvantien2009.com/tags/NPM/"},{"name":"Private Registry","slug":"Private-Registry","permalink":"http://nguyenvantien2009.com/tags/Private-Registry/"},{"name":"NodeJS","slug":"NodeJS","permalink":"http://nguyenvantien2009.com/tags/NodeJS/"}],"author":"Tien Nguyen"},{"title":"Create SSL Certification","slug":"2021/create-ssl-certification","date":"2020-08-19T17:00:00.000Z","updated":"2022-06-02T08:34:48.104Z","comments":true,"path":"2021/create-ssl-certification.html","link":"","permalink":"http://nguyenvantien2009.com/2021/create-ssl-certification.html","excerpt":"SSL is Security Sockets Layers protocol. Secure Sockets Layer (SSL) is a standard security technology for establishing an encrypted link between a server and a client. SSL allows sensitive information such as credit card numbers, social security numbers, and login credentials to be transmitted securely. Table of Content Block Code for practice Update OS And Check OpenSSL version Generate Privite Key Create a Certificate Singning Request (CSR) Generate SSL Certification Result Now all most of device’s browsers warnings when you access to URL that it don’t SSL (HTTPs). And the Google also don’t trust that site in their seaarch engine. So it isn’t good for SEO.","text":"SSL is Security Sockets Layers protocol. Secure Sockets Layer (SSL) is a standard security technology for establishing an encrypted link between a server and a client. SSL allows sensitive information such as credit card numbers, social security numbers, and login credentials to be transmitted securely. Table of Content Block Code for practice Update OS And Check OpenSSL version Generate Privite Key Create a Certificate Singning Request (CSR) Generate SSL Certification Result Now all most of device’s browsers warnings when you access to URL that it don’t SSL (HTTPs). And the Google also don’t trust that site in their seaarch engine. So it isn’t good for SEO. How do SSL Cerification work? Have 7 steps and 4 transfer data flows when 1 SSL run. Block Code for practice use for copy then run 123456sudo apt-get update && sudo apt-get upgradeopenssl version -asudo openssl genrsa -aes128 -out domain.key 2048sudo openssl req -new -days 365 -key domain.key -out domain.csrsudo openssl x509 -in domain.csr -out domain.crt -req \\ -signkey domain.key -days 365 Update OS And Check OpenSSL version12sudo apt-get update && sudo apt-get upgradeopenssl version -a Generate Privite KeySSL use 1-way encryption. The private key is generated in server (web host). Then provide to client when send a request to server. We use openssl library to generate private key for AES 128 algorithm. The result is domain.key file. 1sudo openssl genrsa -aes128 -out domain.key 2048 Create a Certificate Singning Request (CSR)Base on private key, we create a certificate signing request. 1sudo openssl req -new -days 365 -key domain.key -out domain.csr Generate SSL CertificationNow create a SSL certification for 365 days. We need re-create new SSL certification file after 365 days. 12sudo openssl x509 -in domain.csr -out domain.crt -req \\ -signkey domain.key -days 365 ResultWe had 2 files to use in web server or other verification : domain.crt domain.key","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"SSL","slug":"SSL","permalink":"http://nguyenvantien2009.com/tags/SSL/"},{"name":"SSL Certification","slug":"SSL-Certification","permalink":"http://nguyenvantien2009.com/tags/SSL-Certification/"}],"author":"Tien Nguyen"},{"title":"Build Private Docker Registry","slug":"2021/build-private-docker-registry","date":"2020-08-18T17:00:00.000Z","updated":"2022-06-02T08:33:06.812Z","comments":true,"path":"2021/build-private-docker-registry.html","link":"","permalink":"http://nguyenvantien2009.com/2021/build-private-docker-registry.html","excerpt":"","text":"If you are reading this article, I think that you knewn what is docker. As you know, the docker have image, container, volume and network. But the first of them is Docker Image. It help erect to conainers in Docker Deamon after we build by yaml file. We need host to storage them. It’s called the Docker Registry. Table of Contents Why we need private Docker Registry Install Registry by Docker Hub How to use it? Security Registry Setting NGINX Using SSL Using Authentication File Storage Custom Result Testing Errors Code links References Why we need private Docker RegistryAll of guides or documents in the internet, you easy see pull command when start to play with the docker. This command will pull image in Docker Hub. I’s hosted by Docker Inc. We also push our images to that but there are serveral contrains about public/ private project. Beacuse it isn’t a completely free service. Docker Registry help us to manage docker image build version. It does that through tag. Eache build version need assigee it a tag then you can pull image by tag as a build version. We need a private docker registry when use docker in a software company. The source codes need be secured by authentication if want to pull/push. We also do that with Docker Hub but need pay fee to it. Docker Hub does the same. Install Registry by Docker HubWith: server-ip is IP address or host name. :5000 the port used for registry. We can change to other port. 123456789101112# pull and run registry dockerdocker run -d -p 5000:5000 --restart=always --name registry registry:2# pull and run hello-world dockerdocker run hello-world# capture current container by tagging it.docker tag hello-world server-ip:5000/hello-worlddocker images# push to docker registry.docker push server-ip:5000/hello-world To sure that push to registry is successfull. Please check it by CRUL or access it from URL in the browser. 1curl -X GET http://server-ip:5000/v2/_catalog If you don’t use SSL for URL yet. I sure you will have security errors. But we also by pass it when docker daemon --insecure-registry server-ip:5000. Or if you use UNIX OS please {"insecure-registries" : ["server-ip:5000"]} in /etc/docker/daemon.json and if use Window please add server-ip:5000 to Deamon tab of Docker Setting App. How to use it?With: server-ip is IP address private docker registry. hello-world is image’s name that we pushed to docker registry. :5000 only port of docker registry. Of couse we can choose other number if we want. 12345678docker pull server-ip:5000/hello-world# now we can run docker from it's image.docker run --name hello-test server-ip:5000/hello-world # but after run, it will be stop and only show `Hello from Docker`# because it's image do that.docker pull server-ip:5000/hello-world Security Registry SettingAs I know, you have 3 methods to scure a Docker Registry. Use NGINX to require username/password when pulling/pushing an image. Use SSL to secure with environment variables when building a docker container by docker-compose. Use file (htpasswd) for authentication. NGINX UsingWith: ./resources/nginx.conf by /resources/nginx.conf. 1234567891011121314151617181920212223242526272829# 1. Make config folder. mkdir -p auth datanano ./auth/nginx.conf# copy content in file ./resources/nginx.conf# 1.1. Install htpasswd in Unbuntusudo apt install apache2-utils# 2. create username and password: testuser/ testpassworddocker run --rm --entrypoint htpasswd \\ registry:2 -Bbn testuser testpassword > auth/nginx.htpasswd# 3. copy 2 files certification to ./auth folder.# ... [Create cerification](/2020/create-ssl-cerification)cp domain.crt authcp domain.key auth# 4. create docker-compose.yml#... copy from ./resources/registry-docker-compose.yml# 5. stop and start docker composedocker-compose up -d# 6. login then push and pull docker image.docker login -u=testuser -p=testpassword \\ -e=root@example.ch server-ip:5000docker tag ubuntu server-ip:5000/testdocker push server-ip:5000/testdocker pull server-ip:5000/test After login successful, you can pull and push a docker image to docker registry. In this phrase, I created SSL cerification from Cerification SLL. SSL UsingIf you already have a .crt and .key file from your CA. Need change docker-compose to add new environments: Please refer to ssl-docker-compose.yml Authentication FileThe same with steps in use nginx but SSL certification is added to registry enviroment variables. Link to source code. 12345678910111213version: '3'services: registry: image: registry:2 ports: - "443:443" environment: REGISTRY_HTTP_ADDR=0.0.0.0:443 REGISTRY_HTTP_TLS_CERTIFICATE=certs/domain.crt REGISTRY_HTTP_TLS_KEY=certs/domain.key volumes - ./certs:/certs Storage CustomThe image need be storage a place in disk. We also change default path of disk to save with REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY enviroment variable. 1234567891011version: '3'services: registry: image: registry:2 ports: - "5000:5000" environment: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data volumes: - ./data:/data In here, we set REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY variable and add data directory mapping. Result TestingLet test result by bellow code block. 12345docker login -u=testuser -p=testpassword \\ -e=root@example.ch server-ip:5000docker tag ubuntu server-ip:5000/testdocker push server-ip:5000/testdocker pull server-ip:5000/test After push a image you should see result when run: 1curl -X GET http://server-ip:5000/v2/_catalog Output data: 1{"repositories":["hello-world"]} ErrorsIf your registry host don’t apply SSL (can’t call with HTTPs), you will have error about that. Default docker request to https. Please add to client docker config in Deamon. With Linux OS is /etc/docker/deamon.json file. 1{ "insecure-registries" : ["server-ip:5000"] } With Window, in Deamon tab docker app then only need add server-ip:5000. All of OS, we also use command line to set insecure registries. 1docker daemon --insecure-registry server-ip:5000 Code links ssl-docker-compose.yml nginx config registry-docker-compose.yml References Setting up a private Docker registry How to create your own private Docker registry and secure it Authenticate proxy with nginx. Create SSL Cerification","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"Docker","slug":"Docker","permalink":"http://nguyenvantien2009.com/tags/Docker/"},{"name":"Docker Registry","slug":"Docker-Registry","permalink":"http://nguyenvantien2009.com/tags/Docker-Registry/"},{"name":"Docker Repository","slug":"Docker-Repository","permalink":"http://nguyenvantien2009.com/tags/Docker-Repository/"},{"name":"Docker Image Hosting","slug":"Docker-Image-Hosting","permalink":"http://nguyenvantien2009.com/tags/Docker-Image-Hosting/"}],"author":"Tien Nguyen"},{"title":"Join Nodes in MoleculerJS With Microservice","slug":"2021/join-nodes-of-microservice-in-moleculerjs","date":"2020-08-04T17:00:00.000Z","updated":"2022-06-02T08:50:44.838Z","comments":true,"path":"2021/join-nodes-of-microservice-in-moleculerjs.html","link":"","permalink":"http://nguyenvantien2009.com/2021/join-nodes-of-microservice-in-moleculerjs.html","excerpt":"","text":"As you known, the microservices is a design pattern help us build large system. So we need deploy services in many servers together. Those servers must be see and transfer data when a function is called. Table of Content Install Redis Set Transporter in moleculer.config.js file. Test the result References We will have network problems. How can the servers see each other? And keep these connections constantly. Besides, we need to reduct the delay time when transmitting data to each other. Best way, we should use 3rd as Redis, TPC, NATS, MQTT, Kafla… In the moleculerjs, it is shown with name Transporter. The transporter help us set up it’s method and options transporter. The matrix services will monitor services’s lives. The services push/pull messages when they still live. We can show all live services by nodes command line in cmd moleculerjs. Install RedisIn this post, we choose Redis to apply this issue. Please install Redis with Docker for simplicity. Here are them commands to install: 1234docker run --name redis-dev \\ -p 6380:6379 \\ -d redis \\ --requirepass "vts4dev" The --requirepass "vts4dev" is password. It will require when want to access Redis. (You need have Docker basic knowledge). Now use Redis CLI to check result. If you use Window OS, you need download Redis CLI for window. 1.\\redis-cli.exe -h localhost -a vts4dev -p 6380 Set Transporter in moleculer.config.js file.After you have a redis server. We need edit moleculer.config.js at trasporter key. 1234567891011...transporter: { type: "Redis", options: { host: "localhost", port: 6380, password: 'vts4dev', db: 0 }},... Test the resultSo far we need 2 projects to check. Let create 2 moleculerjs projects with moleculer init. Then Install Redis Setup transporter in moleculer.config.js Run nodes command in Moleculer CMD. References Redis Transporter in MoleculerJS Networking","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Microservice","slug":"Microservice","permalink":"http://nguyenvantien2009.com/tags/Microservice/"},{"name":"MoleculerJS","slug":"MoleculerJS","permalink":"http://nguyenvantien2009.com/tags/MoleculerJS/"},{"name":"Transporters","slug":"Transporters","permalink":"http://nguyenvantien2009.com/tags/Transporters/"},{"name":"Cluster Nodes","slug":"Cluster-Nodes","permalink":"http://nguyenvantien2009.com/tags/Cluster-Nodes/"}],"author":"Tien Nguyen"},{"title":"Github Page From Swagger API (OpenAPI)","slug":"2021/github-page-and-openapi","date":"2020-07-07T17:00:00.000Z","updated":"2022-06-02T08:36:04.144Z","comments":true,"path":"2021/github-page-and-openapi.html","link":"","permalink":"http://nguyenvantien2009.com/2021/github-page-and-openapi.html","excerpt":"","text":"Chuẩn bị Tạo tập tin OpenAPI Tạo tập tin index.html Xuất bản lên github page. Tài liệu tham khảo Hiện nay Rest API được sử dụng rộng rãi trên các ứng dụng phần mềm. Nó rất tiện khi kết hợp các dịch vụ với nhau thông qua giao thức HTTP. Mỗi ứng dụng điều muốn cung cấp API để các ứng dụng có thể đấu nối nhằm nhận dữ hay cung cấp dữ liệu cho nhau. Điều này có nghĩa là qui tắc nghiệp vụ của mỗi ứng dụng lại khác nhau nên các API đó cũng sẽ khác nhau. Để các đối tác có thể sử dụng được các API với nhau cần cung cấp tài liệu cho để có thể thực thi. Swagger 2 hay OpenAPI (Swagger 3) là một lựa chọn phổ biến để tạo tài liệu hướng dẫn. Nhưng nó được viết với định dạng yaml hay json thì khó đọc. Có nhiều giải pháp giúp đọc được 2 định dạng này trên dạng web. Trong bài viết này tôi xin giới thiệu cách xuất bản tập tin định dạng yaml (yml) lên github page bằng các sử dụng RedDoc. Chuẩn bịTrước tiên ta cần tạo một thư mục để chứa tập tin định nghĩa thông tin các API dạng yml và index.html. Thư mục này cần được kết nối đến github để tiện cho commit sau này. Trong đó yml là tập tin định nghĩa các API theo định dạng yml hay json. Còn index.html là một tập tin HTML thường đọc CSS, JS từ CDN. Tạo tập tin OpenAPICó thể đặt tên là application.yml. Sau đó viết thông tin khai báo API trong đây. Nếu bạn chưa rõ thì có thể sao chép từ đây (đây là ví dụ). Tạo tập tin index.htmlTôi muốn xuất bản tài liệu dạng web theo cách trình bày của RedDoc. Do đó cần liên kết đến CSS, JS của RedDoc trên CDN. 12345678910111213141516171819<!DOCTYPE html><html> <head> <title>QR Info by VTS Space</title> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet"> <style> body { margin: 0; padding: 0; } </style> </head> <body> <redoc spec-url="https://raw.githubusercontent.com/{username}/{project}/master/application.yml"></redoc> <script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script> </body></html> Bây giờ bạn có thể kiểm tra bằng cách double click vào index.html. Xuất bản lên github page.Hãy commit lên github và vào Setting để cho phép chạy được page trong github. Tại đây bạn có thể thêm các cấu hình về đường dẫn của trang để hiện thị giao diện hướng dẫn các APIs. Tài liệu tham khảo Swagger Editor Redoc API in Github Redoc CLI Document QR Information Document Example QR Information Document Example for Code","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Swagger","slug":"Swagger","permalink":"http://nguyenvantien2009.com/tags/Swagger/"},{"name":"OpenAPI","slug":"OpenAPI","permalink":"http://nguyenvantien2009.com/tags/OpenAPI/"},{"name":"Github","slug":"Github","permalink":"http://nguyenvantien2009.com/tags/Github/"},{"name":"Github Page","slug":"Github-Page","permalink":"http://nguyenvantien2009.com/tags/Github-Page/"},{"name":"Document","slug":"Document","permalink":"http://nguyenvantien2009.com/tags/Document/"}],"author":"Tien Nguyen"},{"title":"Build Dockerfile","slug":"2021/build-dockerfile","date":"2020-07-05T17:00:00.000Z","updated":"2022-06-02T08:30:06.280Z","comments":true,"path":"2021/build-dockerfile.html","link":"","permalink":"http://nguyenvantien2009.com/2021/build-dockerfile.html","excerpt":"","text":"Dockerfile is unit to build image for docker engine of application. We need create file Dockerfile and build this file by docker commanline. The after build success, we have an image in docker engine. Create DockerfileDockerfile need create have name is Dockerfile. We have 14 commands in docker file. FROM re-use image from docker hub. Eg: build docker in Ubuntu or Debian we need OS platform. FROM Debian RUN to run a command line. Eg: RUN echo "Hello world.", when start run docker we will see line Hello world in console. COPY help we copy files or folder to other folder. This command usually use to copy from current folder (contain codes) to application folder of container. ADD also be used to copy files and folder. The same COPY command, but it call add source is URL type or folder/file was ziped. WORKDIR is current working dir. It is same cd command line. All next command will be applied in that folder. ENV help we defined environment variables. Eg: ENV developement. VOLUME defiend folder we want share between container of docker and real PC. Eg: VOLUME dir_path or defined when run docker -v /home/sitesdata:/home/data. USER define user that use to run command line from CMD, RUN, WORKDIR command line. ENTRYPOINT is command line run when start container. E.g: ENTRYPOINT ["command", "param1", ...] CMD same ENTRYPOINT CMD ["command", "param1", ...]. It is shell command line. EXPOSE port that container can listen. We can use that to connect to other container or connect from host. E.g: EXPOSE 9000. LABEL help add information for docker container in metadata. We will see it when use docker inspect. E.g: LABEL name=Test Me\\ address=email@gmail.com ARG defined variable in Dockerfile. MAINTAINER maintain by? Command lines as: ADD, CMD, ENTRYPOINT, WORKDIR… will generate docker images in docker engine. So we need try combine commands to reduct layer images in docker engine. 12345678RUN yum update -y \\ && yum install httpd httpd-tools -y \\ && yum install epel-release -y \\ && yum update -y \\ && yum install htop -y \\ && yum install vim -yENTRYPOINT ["/usr/sbin/httpd", "-D", "FOREGROUND"] Only need 3 image in bellow code. Have 2 image no-name and 1 latest image. We also write docker file use ENV as variables: 1234ENV foo /barWORKDIR ${foo} # WORKDIR /barADD . $foo # ADD . /barCOPY \\$foo /quux # COPY $foo /quux Or use ARG: 123ARG CODE_VERSION=latestFROM base:${CODE_VERSION}CMD /code/run-app VOLUME command lineWe need attention to 3 objects when interact with volume. When a volume can work, it need be enough 3 objects below. Volume instance. Source of volume in host. Target of volume in container. Following are the command lines to help add and delete information about a volume. 12345docker volume lsdocker volume create $volume_namedocker volume inspect $volume_namedocker volume rm $volume_namedocker volume prume VOLUME createCreate new volume and map it to docker container. 12docker volume create --opt device=/home/mydata --opt type=none --opt o=bind mydiskdocker run -it -v mydisk:/home/sites ubuntu VOLUME mappingMount volume when run docker container. 123... -v /source:/target# or... --mount source=source_dir,target=target_dir We also define in Dockerfile by VOLUME command. 1VOLUME /dir VOLUME sharingWe also share disk from container to other container by --volumes-from $container_name/$container_id. 1docker run -it --volumes-from container_first ubuntu Check HEALTHYCall to URL to info that docker will live. 12HEALTHCHECK --interval=5m --timeout=3s \\ CMD curl -f http://localhost/ || exit 1 Build Docker file12docker build --no-cache -t $tag_name .docker build --no-cache -t $tag_name -f $path_folder_docker . --no-cache help not use caching in docker enigne. It will download and re-build as new. -t tage name of docker imgage. We usually add version in tag name. We also can use multiple tag names. E.g: whenry/fedora-jboss:latest -t whenry/fedora-jboss:v2.1. Now we can check result by docker images. Run Docker Image1docker run -it --name $name_service $image_name Dockerfile TemplateCreate Dockerfile in nodejs project. 1234567891011121314FROM debian:latestRUN apt-get update && apt-get install -y \\ git \\ npm \\ nodejs RUN mkdir /appRUN git clone "http://gitlab.vtsspace.com/qr-info/openapi-service.git" /appWORKDIR /appRUN npm installCMD ["npm", "start"] References Sử dụng Dockerfile để tự động tạo các image trong Docker Dockerfile Reference","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"Docker","slug":"Docker","permalink":"http://nguyenvantien2009.com/tags/Docker/"},{"name":"Dockerfile","slug":"Dockerfile","permalink":"http://nguyenvantien2009.com/tags/Dockerfile/"},{"name":"Swagger","slug":"Swagger","permalink":"http://nguyenvantien2009.com/tags/Swagger/"},{"name":"OpenAPI","slug":"OpenAPI","permalink":"http://nguyenvantien2009.com/tags/OpenAPI/"}],"author":"Tien Nguyen"},{"title":"Build Rest API Document by OpenAPI (Swagger 3.x) in Virtual Studio Code.","slug":"2021/openapi-swagger-in-vs","date":"2020-06-15T17:00:00.000Z","updated":"2022-06-02T08:51:53.183Z","comments":true,"path":"2021/openapi-swagger-in-vs.html","link":"","permalink":"http://nguyenvantien2009.com/2021/openapi-swagger-in-vs.html","excerpt":"","text":"We have many ways to design software. But we need support tools for design. OpenAPI will tools help us design Rest API document. We also use it to share members in team and archived documents in the project documents. We can use code to build documents. It is very fast and bettter for developers. It also export to HTML and PDF to share member in team and customer. We also should use plugin in Editor as Visual Studio Code, Sublime Text to support auto-complete and check syntax when code to create API documents. In the article, we use OpenAPI Editor and Swagger Viewer in Virtual Studio Code. Swagger and OpenAPI Swagger Ecosystem Swagger UI: Web UI to view API. Swagger Editor: Web Editor Online. Swagger Codegen: It help we generate client code to access API. It was supported many languages: C#, Java, NodeJS, Python, Go… How to use it?. OpenAPI ElementsWhen we create new document for Rest API, need knowns elements in OpenAPI. OpenAPI Specification is created by .yml, .json. But .yml be used popular. OverviewOnly 7 elements in OpenAPI 3.x. 1. Info2. Host 3. SecurityUse Bearer authentication with JWT (JSON Web Token). In components property we need add securitySchemes property. 123456components: securitySchemes: Bearer: type: http scheme: bearer bearerFormat: JWT Then in security property in root. 12security: - Bearer: [] Now we can use this security in path items. 123# In path item property. security: - Bearer: [] We can click lock icon in website document to input token for authentication. Only need input token, no need Bearer. 4. PathsPaths contain many path item. They are interface APIs that be generated to the document. We need URL, methods (GET, POST, PUT,DELETE…) Includes: summary: description: tags: security: parameters: requestBody: responses: 5. Tags6. ExternalDocs7. ComponentsPaths: securitySchemes: Defined elements use for security. schemas: Define schema need use for reference #/components/.... links: callbacks: OpenAPI GUIOpenAPI-GUI v3OpenAPI Editor Online: https://mermade.github.io/openapi-gui/ OpenAPI-GUI v3 is online tools help design Rest API document. We can import/export documents from json, yml file from upload and export button. There are elements: header: it is same with info path. servers: it is same with host path. security: it is same with security path. tags: it is same with tags path. schemas: it is same with components.schemas path. Swagger Editor DocumentationIt is opensource in NodeJS with web platform Github. We can download and install it by npm. 1234npm install -g http-serverwget https://github.com/swagger-api/swagger-editor/releases/download/v2.10.4/swagger-editor.zipunzip swagger-editor.ziphttp-server swagger-editor Or use Docker. 12docker pull swaggerapi/swagger-editordocker run -p 80:8080 swaggerapi/swagger-editor OpenAPI in Virtual CodeIt is difficult to remember document structure of OpenAPI. OpenAPI (Swagger) EditorSwagger ViewerName in Vitual Studio Code Plugin arjun.swagger-viewer. To start Open the swagger file and press F1. Run the Command Preview Swagger.Or Press Shift + Alt + P After that open browser.Example: http://localhost:18512 Deploy API DocumentWhen build api document by yaml, we can not run content in web ui if don’t have support by some editor online. But with config yml file, we can auto start server web in local PC by use swagger-ui-express package in npm. 1npm install swagger-ui-express Then create index.js file to start service. 123456789const express = require('express');const app = express();const swaggerUi = require('swagger-ui-express');const swaggerDocument = require('./swagger.json');app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));const port = 3000;app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`)); But if need load .yml file, we need install yamljs to parse yaml format. 1npm install --save yamljs Now index.js file will be changed. 12345678910const express = require('express');const app = express();const swaggerUi = require('swagger-ui-express');const YAML = require('yamljs');const swaggerDocument = YAML.load('./swagger.yaml');app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));const port = 3000;app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`)); If we have any issues when run index.js file. we need re-check version of NodeJS and ExpressJS in swagger-ui-express. Fake response of API in SwaggerSwagger Defination only help us show structure data of APIs in the website. But now we can not run result when click button try it in web ui. We don’t have server to response apis. In this case, we also use swagger package in npm. When use call API we can forward the request to response from JSON file. And we need create this file in ./api/controllers/ folder. And also add x-swagger-router-controller property in path of swagger. 123npm install -g swaggerswagger project create hello-worldswagger project edit Now editor web UI will show to define config API. And add new file ./api/controllers/hello_world.js to response data. 12345function hello(req, res) { var name = req.swagger.params.name.value || 'stranger'; var hello = util.format('Hello, %s', name); res.json(hello);} And add new property in API defination file. 123paths: /hello: x-swagger-router-controller: hello_world Now we need start service swagger project start command. Then test with command line. 12$ curl http://127.0.0.1:10010/hello?name=Scott"Hello, Scott!" References Basic Structure API Server and Path base Media Type Paths and Operations Describing Parameters Parameters Serialization Describing Request Body Describing Responses Data Model (Schemas): Data Types, Enums, Dictionaries, Hashmaps, Associative Arrays,oneOf, anyOf, allOf, not, Inheritance, and Polymorphism, Representing XML, Supported JSON Schema Keywords Adding Examples Authentication: Basic, Bearer, API Key, OAuth2, OpenID Connect Discovery Deploy API Document to web server in NodeJS. Fake response API document in NodeJS.","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Swagger","slug":"Swagger","permalink":"http://nguyenvantien2009.com/tags/Swagger/"},{"name":"OpenAPI","slug":"OpenAPI","permalink":"http://nguyenvantien2009.com/tags/OpenAPI/"},{"name":"Document","slug":"Document","permalink":"http://nguyenvantien2009.com/tags/Document/"},{"name":"Rest","slug":"Rest","permalink":"http://nguyenvantien2009.com/tags/Rest/"},{"name":"API","slug":"API","permalink":"http://nguyenvantien2009.com/tags/API/"}],"author":"Tien Nguyen"},{"title":"Build and Deploy Docker","slug":"2021/build-and-deploy-docker","date":"2020-06-08T17:00:00.000Z","updated":"2022-06-02T08:29:59.506Z","comments":true,"path":"2021/build-and-deploy-docker.html","link":"","permalink":"http://nguyenvantien2009.com/2021/build-and-deploy-docker.html","excerpt":"We will build and deploy Dockerfile with tags (use tags as version deploy). We need 3 steps in this process.","text":"We will build and deploy Dockerfile with tags (use tags as version deploy). We need 3 steps in this process. Step 1: Check container and image in current system. 12345# show docker container with name and imagedocker ps -a '{{ .Names }} \\t\\t {{ .Image }}'# show imagesdocker images Step 2: Remove container and images 12345# remove imagedocker rmi -f posems-service:0.0.2 # image name and tag of image# remove containerdocker rm -f posems-service # use `-f` help ignore container is running or not? Step 3: Build and Run 12345678910# Build docker from docker imagedocker build -t posems-service:0.0.2 . # Format{image}:{tag}# Run docker image with port and `-restart=always`docker run --restart=always \\ --name posems-service \\ -p 3000:3000 \\ -p 3001:3001 \\ -p 3002:3002 \\ posems-service:0.0.2","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"Docker","slug":"Docker","permalink":"http://nguyenvantien2009.com/tags/Docker/"},{"name":"Build Docker","slug":"Build-Docker","permalink":"http://nguyenvantien2009.com/tags/Build-Docker/"},{"name":"Deploy Docker","slug":"Deploy-Docker","permalink":"http://nguyenvantien2009.com/tags/Deploy-Docker/"},{"name":"Dockerfile","slug":"Dockerfile","permalink":"http://nguyenvantien2009.com/tags/Dockerfile/"}],"author":"Tien Nguyen"},{"title":"Học Và Nghiên Cứu Bằng Phương Pháp STAR","slug":"2021/hoc-voi-phuong-phap-STAR","date":"2020-06-08T17:00:00.000Z","updated":"2022-06-02T08:47:31.447Z","comments":true,"path":"2021/hoc-voi-phuong-phap-STAR.html","link":"","permalink":"http://nguyenvantien2009.com/2021/hoc-voi-phuong-phap-STAR.html","excerpt":"STAR được xem như là một phương pháp học những kỹ năng, kiến thức mới. Nó được viết tắt bởi See - Think - Act - Reflect. Được hiểu như là: Đọc - Nghĩ - Làm - Rút kinh nghiệm. See Think Act Reflect","text":"STAR được xem như là một phương pháp học những kỹ năng, kiến thức mới. Nó được viết tắt bởi See - Think - Act - Reflect. Được hiểu như là: Đọc - Nghĩ - Làm - Rút kinh nghiệm. See Think Act Reflect 1. See: Đọc, Quan sát, Trãi nghiệmNên đọc ít nhất 10 bài viết về vấn đề mình đang cần tìm hiểu để thấy được tổng quan nhưng gì đang có. Tài liệu có thể tìm trên Goolge hoặc kho tài liệu chuyên ngành tùy vào lĩnh vực đang tìm hiểu. Trong quá trình đọc cần cố gắn đặt mình vào hoàn cảnh đó để sinh ra cảm nhận tốt đồng thời nó cũng giúp ta có thể nhớ lâu hơn. Hiển nhiên ta không thể 100% vào hoàn cảnh vì ta đã chưa từng trong đó. Nhưng cảm giác phần nào sẽ giúp chính xác hơn. 2. Think: Tổng hợp, Đánh giá, Phân tíchĐừng dừng ở chỉ đọc. Hãy tổng hợp lại thành một bài viết cho bản thân mình dễ hiểu hơn. Đôi khi một cuốn sách chỉ cần tổng hợp thành 1 trang. Nhưng đừng quá tham vọng vì nó sẽ không truyền tải đủ. Tài liệu tổng hợp này chỉ mình ta mới hiểu nó. Đặt những câu hỏi giúp sự thật nhanh chóng lộ diện hơn. Đừng ngần ngại đối đầu với nó. Tham gia các diễn đàn, bình luận và phản biện là một biện pháp giúp ta làm rõ nó tốt hơn. Đưa ra những biện luận trái ngược và cố gắn giải thích hợp lý chúng. Khi mọi thứ đã hợp lý thì kiến thức của bạn sẽ được nhớ lâu hơn. Như thuyết tương đối là một công trình vĩ đại nhưng ai cũng hiểu và xem nó là hiển nhiên. Vì ai cũng cảm nhận được và thấy nó hàng ngày. 3. Act: Thử nghiệm và Đo lường.Lập kế hoạc hành động để thử nghiệm những gì ta đang nghi ngờ. Khi thực hiện thì ta mới có cảm giác thật. Kiến thức lúc đó chuyển thành cảm giác và lưu thành một dạng khác dễ nhớ hơn trong đầu. Đừng làm theo cảm tính. Mọi hoạt động cần có kế hoạch và phải có mục tiêu. Để đánh giá mục tiêu đạt được hay không cần có các số liệu đo lường. Nhưng hãy cần thận với số liệu. Nó là một con dao 2 lưỡi nếu ta nhìn nhận sai. 4. Reflect: Phản chiếu, Đúc kết và Rút kinh nghiệm.Hãy mường tượng đến các vấn đề tương tự. Liệu có áp dụng được cho nó không? Thường thì ta sẽ áp dụng cho nhiều hiện tượng tương tự. Khi làm xong cần đánh giá đạt được mong muốn không? Ưu và nhược điểm của nó thế nào? Thường nhưng tìm hiểu không được viết lại thành một báo cáo kết quả hay không đưa ra kết luận nào. Từ đó nó không được bộ não ta đóng gói để lưu trữ lại. Nếu cần thiết thì cải tiến và tin chỉnh để khắc phục các nhược điểm.","categories":[{"name":"Lý luận","slug":"Ly-luan","permalink":"http://nguyenvantien2009.com/categories/Ly-luan/"}],"tags":[{"name":"Star","slug":"Star","permalink":"http://nguyenvantien2009.com/tags/Star/"},{"name":"Research","slug":"Research","permalink":"http://nguyenvantien2009.com/tags/Research/"},{"name":"Learn","slug":"Learn","permalink":"http://nguyenvantien2009.com/tags/Learn/"}],"author":"Tiển Nguyễn"},{"title":"Ionic References","slug":"2021/ionic-references","date":"2020-06-08T17:00:00.000Z","updated":"2022-06-02T08:51:01.729Z","comments":true,"path":"2021/ionic-references.html","link":"","permalink":"http://nguyenvantien2009.com/2021/ionic-references.html","excerpt":"","text":"Theme Setting Theme color generator","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Starter","slug":"Starter","permalink":"http://nguyenvantien2009.com/tags/Starter/"},{"name":"Ionic","slug":"Ionic","permalink":"http://nguyenvantien2009.com/tags/Ionic/"},{"name":"References","slug":"References","permalink":"http://nguyenvantien2009.com/tags/References/"}],"author":"Tien Nguyen"},{"title":"Use Populates to Relate Modes in MoleculerJS.","slug":"2021/use-populate-to-relate-model-in-moleculer","date":"2020-06-08T17:00:00.000Z","updated":"2022-06-02T09:03:22.721Z","comments":true,"path":"2021/use-populate-to-relate-model-in-moleculer.html","link":"","permalink":"http://nguyenvantien2009.com/2021/use-populate-to-relate-model-in-moleculer.html","excerpt":"","text":"Populates add in settings of a service. Name of poplate need same name of fields need link data together. Có 3 cách sử dụng: Popular was defined by string of action name. Add object to field need populate with action and params. { name: "v1.UserInfo.name", params: { fields: ["id", "name"] } } Or add function with params as: (ids, docs, rule, ctx) => { ... }. Reference https://www.npmjs.com/package/moleculer-db#populating","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Moleculer","slug":"Moleculer","permalink":"http://nguyenvantien2009.com/tags/Moleculer/"},{"name":"Populate","slug":"Populate","permalink":"http://nguyenvantien2009.com/tags/Populate/"},{"name":"Model","slug":"Model","permalink":"http://nguyenvantien2009.com/tags/Model/"}],"author":"Tien Nguyen"},{"title":"Tools Ecosystem Support Developers","slug":"2021/Tools ecosystem support developers","date":"2020-06-06T17:00:00.000Z","updated":"2022-06-02T09:03:04.839Z","comments":true,"path":"2021/Tools ecosystem support developers.html","link":"","permalink":"http://nguyenvantien2009.com/2021/Tools%20ecosystem%20support%20developers.html","excerpt":"This article talk about tools support for developers in software company. Almost of them are free (or free version). We need link them together become a ecosystem support develop software process of company.","text":"This article talk about tools support for developers in software company. Almost of them are free (or free version). We need link them together become a ecosystem support develop software process of company. Tools Gitlab Gitlab Runner Slack Zoom Trello Docker","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Developer Tools","slug":"Developer-Tools","permalink":"http://nguyenvantien2009.com/tags/Developer-Tools/"},{"name":"Management Tools","slug":"Management-Tools","permalink":"http://nguyenvantien2009.com/tags/Management-Tools/"},{"name":"Gitlab","slug":"Gitlab","permalink":"http://nguyenvantien2009.com/tags/Gitlab/"},{"name":"Gitlab Runner","slug":"Gitlab-Runner","permalink":"http://nguyenvantien2009.com/tags/Gitlab-Runner/"},{"name":"Slack","slug":"Slack","permalink":"http://nguyenvantien2009.com/tags/Slack/"},{"name":"Zoom","slug":"Zoom","permalink":"http://nguyenvantien2009.com/tags/Zoom/"},{"name":"Trello","slug":"Trello","permalink":"http://nguyenvantien2009.com/tags/Trello/"},{"name":"Docker","slug":"Docker","permalink":"http://nguyenvantien2009.com/tags/Docker/"}],"author":"Tien Nguyen"},{"title":"Send Notification When Update Code in Gitlab.","slug":"2021/notify-when-update-code-in-gitlab","date":"2020-06-06T17:00:00.000Z","updated":"2022-06-02T08:51:47.863Z","comments":true,"path":"2021/notify-when-update-code-in-gitlab.html","link":"","permalink":"http://nguyenvantien2009.com/2021/notify-when-update-code-in-gitlab.html","excerpt":"We can connect between Gitlab and Slack for sending notifications. Need webhook URL from Slack and setting Slack Notification in Gitlab.","text":"We can connect between Gitlab and Slack for sending notifications. Need webhook URL from Slack and setting Slack Notification in Gitlab. When the members change code in gitlab, we need be notified to Slack Application. It help us see change in project. In Gitlab is supported Slack Notification plugin and Slack provide Webhook feature. They will help perform this process. SlackIn the Slack, we need add new application. Choose App then search webhook. Add Incoming Webhooks to Slack App. Gitlab Chose Project. In left menu, Chose Settings -> Integrations And configurate for Webhook. We need URL webhook and Username. The username will show as author message. Webhook URL: get from Webhook URL in Slack App. Username: We can input any username that we want. Icon: We also upload icon to show in Slack when send notification. Channel and TriggerGitlab will enable triggers to send to channel in Slack. We need define channel for each triggers need. The Gitlab have triggers: push, comment, issue…","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Gitlab","slug":"Gitlab","permalink":"http://nguyenvantien2009.com/tags/Gitlab/"},{"name":"Slack","slug":"Slack","permalink":"http://nguyenvantien2009.com/tags/Slack/"},{"name":"Git","slug":"Git","permalink":"http://nguyenvantien2009.com/tags/Git/"},{"name":"Notification","slug":"Notification","permalink":"http://nguyenvantien2009.com/tags/Notification/"},{"name":"Slack Webhook","slug":"Slack-Webhook","permalink":"http://nguyenvantien2009.com/tags/Slack-Webhook/"}],"author":"Tien Nguyen"},{"title":"Width Size of Devices Use in CSS","slug":"2021/width-size-of-devices","date":"2020-06-06T17:00:00.000Z","updated":"2022-06-02T09:03:58.999Z","comments":true,"path":"2021/width-size-of-devices.html","link":"","permalink":"http://nguyenvantien2009.com/2021/width-size-of-devices.html","excerpt":"In CSS, when apply for responsive design. We need care to screen width of device. The Bootstrap and other CSS framework had standard width size of screen as Phone, Tablet, Laptop and Desktop. Size of the devices base on min-width of css with media type.","text":"In CSS, when apply for responsive design. We need care to screen width of device. The Bootstrap and other CSS framework had standard width size of screen as Phone, Tablet, Laptop and Desktop. Size of the devices base on min-width of css with media type. Have many styles for width of devices. But only 4 types for them. With 3 Screen size With 4 Screen size With 5 Screen sizeList width CSS screen for devices: Short Min Width Container Width Devices CSS xs 0 0 Phone Portrait no need defien sm 576 540 Phone Landscapse @media (min-width: 576px) { ... } md 768 720 Tablet @media (min-width: 768px) { ... } lg 992 960 Laptop or Desktop @media (min-width:992px) { ... } xl 1200 1140 Wide Desktop @media (min-width:1200px) { ... } With 6 screen sizeWe have 4 devices (phone, tablet, laptop, deskop) and 6 screen size.","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Device size","slug":"Device-size","permalink":"http://nguyenvantien2009.com/tags/Device-size/"},{"name":"CSS Screen","slug":"CSS-Screen","permalink":"http://nguyenvantien2009.com/tags/CSS-Screen/"},{"name":"Bootstrap Screen","slug":"Bootstrap-Screen","permalink":"http://nguyenvantien2009.com/tags/Bootstrap-Screen/"}],"author":"Tien Nguyen"},{"title":"Cách Thêm Chữa Ký Vào Tập Tin PDF","slug":"2021/sign-signtature-to-pdf","date":"2020-05-30T17:00:00.000Z","updated":"2022-06-02T09:00:50.685Z","comments":true,"path":"2021/sign-signtature-to-pdf.html","link":"","permalink":"http://nguyenvantien2009.com/2021/sign-signtature-to-pdf.html","excerpt":"","text":"Hợp đồng, đơn hàng… cần có chữ ký để thể hiện được tính hợp pháp. Thường thì ta in ra các bản giấy để lý sau đó chụp ảnh lại để gửi lại cho các bên. Nhưng trong các ứng dụng đọc PDF cũng có hỗ trợ thêm chữ ký vào tập tin đó. Thêm chữ ký trong Poxit ReaderMở tập tin PDF bằng Poxit Reader. Làm theo trình tự bên dưới: 1Home -> PDF Sign Protect -> Add new Signature -> Draw Signature Sau khi đã vẽ xong chữ ký thì chữ ký sẽ được nằm trong tập tin PDF. Nhiệm vụ của ta đơn giản chỉ là kéo chữ ký đặt đúng nơi và điều chỉnh kích thước chữ ký cho phù hợp. Nhớ lưu lại tập tin để đảm bảo chữ ký đã được nằm trên tập tin PDF.","categories":[{"name":"Thủ thuật","slug":"Thu-thuat","permalink":"http://nguyenvantien2009.com/categories/Thu-thuat/"}],"tags":[{"name":"PDF","slug":"PDF","permalink":"http://nguyenvantien2009.com/tags/PDF/"},{"name":"Document","slug":"Document","permalink":"http://nguyenvantien2009.com/tags/Document/"},{"name":"Signature","slug":"Signature","permalink":"http://nguyenvantien2009.com/tags/Signature/"}],"author":"Tiển Nguyễn"},{"title":"Write Document With Swagger Editor","slug":"2021/write-document-with-swagger-editor","date":"2020-05-24T17:00:00.000Z","updated":"2022-06-02T09:04:04.544Z","comments":true,"path":"2021/write-document-with-swagger-editor.html","link":"","permalink":"http://nguyenvantien2009.com/2021/write-document-with-swagger-editor.html","excerpt":"","text":"About Swagger EditorRequires: 123NPM 6.xNode.js 12.xNPM 6.x Deploy by Docker12docker pull swaggerapi/swagger-editordocker run -d -p 80:8080 swaggerapi/swagger-editor We also run swagger from resource with JSON file. In below code we will build swagger by swagger.json. 1234docker run -d -p 80:8080 \\ -e URL=/foo/swagger.json \\ -v /bar:/usr/share/nginx/html/foo \\ swaggerapi/swagger-editor References[1] Github Opensource Swagger Editor (License Apache 2.0) [https://github.com/swagger-api/swagger-editor].","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"document","slug":"document","permalink":"http://nguyenvantien2009.com/tags/document/"},{"name":"document rest api","slug":"document-rest-api","permalink":"http://nguyenvantien2009.com/tags/document-rest-api/"},{"name":"swagger","slug":"swagger","permalink":"http://nguyenvantien2009.com/tags/swagger/"},{"name":"swagger edit","slug":"swagger-edit","permalink":"http://nguyenvantien2009.com/tags/swagger-edit/"}],"author":"Tien Nguyen"},{"title":"Pankod - the Best Framework for MoleculerJS","slug":"2021/pankod-the-best-framework-for-microservice","date":"2020-05-23T17:00:00.000Z","updated":"2022-06-02T08:52:16.542Z","comments":true,"path":"2021/pankod-the-best-framework-for-microservice.html","link":"","permalink":"http://nguyenvantien2009.com/2021/pankod-the-best-framework-for-microservice.html","excerpt":"","text":"About Moleculer FrameworkMoleculer is a fast, modern and powerful microservice framework for NodeJS. It is effecient, reliable and scalable service. Moleculer provide many features for building and managing your microservice. Features: Support event-drive architecture with balancing. Support caching as Redis and Memory. Pluggable transporters (TCP, NATS, MQTT, Redis, NATS Streaming, Kafka). Build in health monitoring and metrics. Many fault tolerance features (Circuit Breaker, Bulkhead, Retry, Timeout, Fallback). Load balancing as round-robin, random, cpu-usege, latency. Service Helper will help easy contact between services together. About Pankod Framework The project’s name is moleculerjs-boilerplate. It is includes: MoleculerJS, Typescript, Eslint, TypeORM, Jest (for testing), Swagger (for document REST api), Docker (build and deploy), Project CLI (command line for build project)… Project CLIProject CLI is a command line interface project. It used to build service, interface, utils, unit, service helper… Project Structure1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798.├── public│ ├── banner.png│ ├── favicon.ico│ └── index.html├── services│ ├── api.service.ts│ ├── attack.service.ts│ ├── index.ts│ └── planet.service.ts├── src│ ├── Entities│ │ ├── Connection.ts│ │ ├── Planet.ts│ │ ├── Weapon.ts│ │ └── index.ts│ ├── Interfaces│ │ ├── Meta│ │ │ ├── DamageMetaOutDto.d.ts│ │ │ └── index.ts│ │ ├── Repositories│ │ │ ├── Planet│ │ │ │ ├── DecreaseShieldOutDto.d.ts│ │ │ │ └── index.ts│ │ │ └── Weapon│ │ │ ├── DecreaseAmmoOutDto.d.ts│ │ │ └── index.ts│ │ ├── Services│ │ │ ├── Attack│ │ │ │ ├── IAttack.d.ts│ │ │ │ └── index.ts│ │ │ └── Planet│ │ │ ├── IPlanet.d.ts│ │ │ └── index.ts│ │ └── index.ts│ ├── Meta│ │ ├── CalculateMeta.ts│ │ └── index.ts│ ├── Repositories│ │ ├── ErrorHelpers.ts│ │ ├── Planet.ts│ │ ├── Shared.ts│ │ ├── Weapon.ts│ │ └── index.ts│ └── ServiceHelpers│ ├── AttackHelper.ts│ ├── PlanetHelper.ts│ └── index.ts├── swagger│ ├── config.js│ ├── index.js│ ├── package.json│ └── swagger.json├── test│ ├── Config│ │ ├── Connection.ts│ │ ├── SetupDatabase.ts│ │ └── mock.setup.ts│ ├── Integration│ │ ├── attack.spec.ts│ │ └── planet.spec.ts│ ├── Seeder│ │ ├── AttackSeeder.ts│ │ ├── PlanetSeeder.ts│ │ └── index.ts│ ├── Unit│ │ ├── Helper│ │ │ ├── AttackHelper.spec.ts│ │ │ └── PlanetHelper.spec.ts│ │ ├── Meta│ │ │ └── CalculateMeta.spec.ts│ │ ├── MicroServices│ │ │ ├── attack.spec.ts│ │ │ └── planet.spec.ts│ │ └── Repositories│ │ ├── ErrorHelpers.spec.ts│ │ ├── Planet.spec.ts│ │ └── Weapon.spec.ts│ └── Utils│ ├── BrokerHelper.ts│ ├── DummyContext.ts│ └── index.ts├── Dockerfile├── LICENSE├── README.md├── banner.png├── cli.gif├── db.sqlite├── db.sqlite.example├── docker-compose.env├── docker-compose.yml├── moleculer.config.ts├── moleculerjs-cover.png├── package-lock.json├── package.json├── swaggerConfig.json├── tsconfig.json└── tsconfig.production.json References[1] Pankod Opensource [https://pankod.github.io/moleculerjs-boilerplate/].","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"NodeJS","slug":"NodeJS","permalink":"http://nguyenvantien2009.com/tags/NodeJS/"},{"name":"Microservice","slug":"Microservice","permalink":"http://nguyenvantien2009.com/tags/Microservice/"},{"name":"MoleculerJS","slug":"MoleculerJS","permalink":"http://nguyenvantien2009.com/tags/MoleculerJS/"},{"name":"Pankod","slug":"Pankod","permalink":"http://nguyenvantien2009.com/tags/Pankod/"},{"name":"Framework NodeJS","slug":"Framework-NodeJS","permalink":"http://nguyenvantien2009.com/tags/Framework-NodeJS/"}],"author":"Tien Nguyen"},{"title":"Hexo Command Line","slug":"2021/hexo-command","date":"2020-05-17T17:00:00.000Z","updated":"2022-06-02T08:36:58.515Z","comments":true,"path":"2021/hexo-command.html","link":"","permalink":"http://nguyenvantien2009.com/2021/hexo-command.html","excerpt":"","text":"2. Những lệnh cơ bản123456# generate HTML (static) files in `public` folder.hexo generate# deploy to git repositoryhexo deployhexo -g deploy # generate before deploy Nếu có đang sử dụng gói hexo-generator-json-content thì khi chạy hexo serve hay hexo generate thì dữ liệu sẽ được đưa vào tính năng tìm kiếm giúp tìm kiếm thông tin trên box search. 3. Tài liệu tham khảo[1] Hexo Command https://hexo.io/docs/commands.html","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Document","slug":"Document","permalink":"http://nguyenvantien2009.com/tags/Document/"},{"name":"Hexo","slug":"Hexo","permalink":"http://nguyenvantien2009.com/tags/Hexo/"},{"name":"Hexo Command","slug":"Hexo-Command","permalink":"http://nguyenvantien2009.com/tags/Hexo-Command/"}],"author":"Tien Nguyen"},{"title":"Kill a Process by Port in Window and Linux","slug":"2021/kill-process-by-port","date":"2020-05-17T17:00:00.000Z","updated":"2022-06-02T08:51:04.693Z","comments":true,"path":"2021/kill-process-by-port.html","link":"","permalink":"http://nguyenvantien2009.com/2021/kill-process-by-port.html","excerpt":"","text":"Nội dung: Kill Process trong Linux Kill Process trong Window Để dừng một quá trình đang chạy trên Linux bởi thông tin từ số port. Chúng ta có thể dùng lệnh. Trong đó 8080 là số port mà ta cần hủy quá trình xử lý. Lệnh bên dưới thường được sử dụng để hủy một qui trình đang được khỏi chạy từ NodeJS. Kill Process trong LinuxTìm kiếm Process ID trong Linux từ dòng lệnh bên dưới. Trong đây tôi đang tìm những process ID nào đang có port là 80. 1netstat -ap | grep :80 Sau đó chọn process id để kill nó. 1kill -9 $process_id Ta cũng có thể bỏ qua 2 bước trên và dugf lệnh kill process trực tiếp thông qua việc tìm kiếm với port. 1kill -9 $(sudo lsof -t -i:8080) Process ID hoặc là thông tin chi tiết của process: 12lsof -t -i:8080lsof -i:8080 Kill Process trong WindowTìm process id với port từ dòng lệnh bên dưới. 1netstat -aon | findstr :80 Sau đó chọn process id để kill nó. 1tasktask /F /PID $process_id","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Server","slug":"Server","permalink":"http://nguyenvantien2009.com/tags/Server/"},{"name":"Linux","slug":"Linux","permalink":"http://nguyenvantien2009.com/tags/Linux/"},{"name":"Window","slug":"Window","permalink":"http://nguyenvantien2009.com/tags/Window/"},{"name":"Kill","slug":"Kill","permalink":"http://nguyenvantien2009.com/tags/Kill/"},{"name":"Kill Process","slug":"Kill-Process","permalink":"http://nguyenvantien2009.com/tags/Kill-Process/"}],"author":"Tien Nguyen"},{"title":"Thiết Lập Tường Lửa Trên Ubuntu","slug":"2021/setting-firewall-in-ubuntu","date":"2020-05-17T17:00:00.000Z","updated":"2022-06-02T08:52:59.245Z","comments":true,"path":"2021/setting-firewall-in-ubuntu.html","link":"","permalink":"http://nguyenvantien2009.com/2021/setting-firewall-in-ubuntu.html","excerpt":"","text":"Để giảm đi khả năng tấn công không cần thiết, chúng ta nên kích hoạt tường lửa. Chỉ cho phép những cổng và giao thức chúng ta có thể kiểm soát được truy cập hệ thống. 12# check status firewall enable/disable.sudo ufw status verbose 1. Cài đặt tường lửaCài đặt ứng dụng tường lửa trên Linux 1sudo apt-get install ufw Cho phép tường lửa hoạt động trên IP6. 123456# open ufw file in OS.sudo nano /etc/default/ufw# find and set true for IP6#...IPV6=true#... 2. Thiết lập tường lửa cơ bảnNên sử dụng thiết lập mặt định cấp vào cho tất cả và ra thì được cho phép. Khi khai báo lệnh này cần lưu ý đến ssh (22) đã được cho phép chưa. Nếu ta đã cấm thì ngay cả ssh (22) sẽ không thể truy cập được. 12345678910111213# This is important commandsudo ufw allow ssh# orsudo ufw allow 22sudo ufw default deny incomingsudo ufw default allow outgoing# Enable/ Disable Firewall and check status of firewall.sudo ufw enablesudo ufw disablesudo ufw statussudo ufw reset 3. Thiết lập sự cho phép/ cấm theo.3.1. Cổng (port)Đây là cách thiết lập đến một cổng cụ thể. 12sudo ufw allow 80sudo ufw deny 80 3.2. IP Address.Hai dòng lệnh bên dưới là chép đến 1 cụ thể cho tất cả các port hoặc chỉ cho port 22. 12sudo ufw allow from 15.15.15.51sudo ufw allow from 15.15.15.51 to any port 22 Hoặc cho phép theo một dãy IP nào đó. Đoạn lệnh bên dưới là cho phép các máy có ip từ 15.15.15.0 đến 15.15.15.24. Tương tự ta có thể cho phép tất cả các port hoặc chỉ cho phép port 22. 12sudo ufw allow from 15.15.15.0/24sudo ufw allow from 15.15.15.0/24 to any port 22 3.3. Mạng cụ thể.Nếu ta cần thiết lập dự trên một mạng nội bộ nào đó cụ thể mà không quan tâm đến IP address của từng máy hay dãy IP address. Ta sẽ thiết lập dựa trên tên của mạng máy tính. Cần lấy tên mạng máy tính. 1ip addr Tiếp đến là thiết lập sự cho phép dựa trên đây. eth0 là tên của mạng. 1sudo ufw allow in on eth0 to any port 80 4. Xóa qui tắc thiết lập.Có 2 cách xóa qui tắc thiết lập: theo số thứ tự hoặc theo tên của qui tắc. Hiển thị thứ tự của qui tắc sau đó chọn qui tắc cần xóa. 12sudo ufw status numberedsudo ufw delete 2 Xóa theo tên qui tắc. Lệnh bên dưới xóa qui tắc cổng 80 hay HTTP. 12sudo ufw delete allow httpsudo ufw delete allow 80 5. Cho phép các ứng dụng thường sử dụng5.1. HTTP Port 8012sudo ufw allow httpsudo ufw allow 80 5.2. HTTPS Port 44312sudo ufw allow httpssudo ufw allow 443 5.3. FTP Port 2112sudo ufw allow ftpsudo ufw allow 21/tcp 5.4. Port cho TCP/UDPNếu ta thiết cho phép hoặc cấm dãy cổng thì ta có thể thiết lập như khối lệnh bên dưới. Dãy cổng sẽ là từ 6000 đến 6007. 12sudo ufw allow 6000:6007/tcpsudo ufw allow 6000:6007/udp Tài liệu tham khảo[1] How To Set Up a Firewall with UFW on Ubuntu 14.04 https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-14-04","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Server","slug":"Server","permalink":"http://nguyenvantien2009.com/tags/Server/"},{"name":"Linux","slug":"Linux","permalink":"http://nguyenvantien2009.com/tags/Linux/"},{"name":"Firewall","slug":"Firewall","permalink":"http://nguyenvantien2009.com/tags/Firewall/"},{"name":"Allow/Disable Accesss Port","slug":"Allow-Disable-Accesss-Port","permalink":"http://nguyenvantien2009.com/tags/Allow-Disable-Accesss-Port/"}],"author":"Tien Nguyen"},{"title":"MoleculerJS Starter","slug":"2021/moleculer-starter","date":"2020-03-28T17:00:00.000Z","updated":"2022-06-02T08:51:38.690Z","comments":true,"path":"2021/moleculer-starter.html","link":"","permalink":"http://nguyenvantien2009.com/2021/moleculer-starter.html","excerpt":"","text":"MoleculerJS StarterAfter we watch overview guide document by Moleculer, now we can start project. Moleculer has Moleculer CLI. It is tool to support us create a project with a template that was built by Moleculer in Github. 1. Khởi tạo dự án.The first, let install moleculer-cli in global mode with -g option. 1moleculer -g install moleculer-cli And initial project with template name is project. Beside Moleculer also support 2 other templates more. There are nano and module. If need we can reference to https://moleculer.services/docs/0.14/moleculer-cli.html#Official-templates. 1moleculer init project project-name Khi chạy dòng lệnh này, nó sẽ hỏi bạn để cấu hình theo ý bạn thông qua các câu hỏi Yes/No. Theo kinh nghiệm thì nếu cái nào bạn không rõ dùng để làm gì thì cư nhấn Enter. Nó sẽ chọn theo lời khuyên tự động. Sau khi thực hiện lệnh này xong. Trong thư mục hiện tại sẽ chứa thêm thư mục project-name do Moleculer vừa tạo ra. Nó đã giúp ta lấy về mẫu cấu trúc dự án trong thư mục này. Để khởi chạy chúng ta cần. 12cd project-namenpm run dev In package.json file, Moleculer has single line in scripts to run with development environment. Block code above help us can start project in development environment. 2. Cấu hình dự án.Open moleculer.config.js to modify: namespace & node: Nee define name of them. They we will be displayed in console. tracing.enable: Set true for it. We need trace data logging. circuitBreaker.enabled: Set true when need use circuit breaker pattern. metrics.enable: Set true when need use Prometheus to report transfer data. 3. Setting DB use MySQL.Project template of Moleculer use MongoDB to store data. But we use MySQL for Structure Database. So need install some module in npm. 12345npm install --save moleculer-db-adapter-sequelizenpm install --save sequelizenpm install --save mysql2# use for .env configurationnpm install --save dotenv 3.1 Use .env to settingCreate .env file then add config URL of MySQL. We also create .env_dev and .env_stg when need alot of environments. 1MYSQL_URI=mysql://user:pass@host:3306/database-name But note, when run need moleculer-runner --env (use .env file). But with moleculer-runner --envfile .env_dev use .env_dev file setting. We need add them in script of package.json. 3.2 Config with MySQL.Access ./mixins/db.mixin.js add script: 12345678if (process.env.MYSQL_URI) { // MySQL adapter const MySQLAdapter = require("moleculer-db-adapter-sequelize"); schema.adapter = new MySQLAdapter(process.env.MYSQL_URI); // collection used in mongodb but MySQL it is table. let table = collection; schema.model = table;} Then go to ./services/product.service.js add model and change settings fields, entity validate. Model setting we need refer to Sequelize. Now it is done. We can npm run dev then open http://localhost:3000 and tracing with http://localhost:3030. And we can list all api list exposed to check what we work.","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"NodeJS","slug":"NodeJS","permalink":"http://nguyenvantien2009.com/tags/NodeJS/"},{"name":"Microservice","slug":"Microservice","permalink":"http://nguyenvantien2009.com/tags/Microservice/"},{"name":"Moleculer","slug":"Moleculer","permalink":"http://nguyenvantien2009.com/tags/Moleculer/"}],"author":"Tien Nguyen"},{"title":"Bắt đầU Wordpress Với Blog Cá Nhân","slug":"2021/wordpress-starter-with-blog","date":"2020-03-21T17:00:00.000Z","updated":"2022-06-02T09:03:56.183Z","comments":true,"path":"2021/wordpress-starter-with-blog.html","link":"","permalink":"http://nguyenvantien2009.com/2021/wordpress-starter-with-blog.html","excerpt":"","text":"Hiện nếu ta sử dụng các theme, plugins mà không có kiểm soát sẽ dẫn đến mất tài khoản. Do đó sưu hướng tôi muốn tự xây dựng cho mình những tính năng mình đang cần để tránh không bị động khi bị hack. Để xây dựng một website Wordpress từ đâu thì cần thực hiện các bước. Tải phiên bản mới nhất của Wordpress. Tạo một Cơ sở dữ liệu để Wordpress có thể kết nối. CSDL đó là MySQL. Sau khi kết nối đến CSDL. Wordpress sẽ sinh ra các bảng. Và bước kế đến là đặt tài khoản Admin cho website. Sau khi đã cài đặt thành công. Ta tiến hành thêm các plugin. Nhưng do giới hạn của web server về độ lớn của tập tin tải lên. Nên ta cần phải thêm dòng php_value max_execution_time 300 trong tập tin .htaccess. Cài đặt plugin Yoast SEO. Cài đặt Wordfence để bảo mật website. Cài đặt UpdraftPro để sao lưu website. Tạo một theme Starter từ website online https://underscores.me/. Với tên blog-theme.zip/ Tải tập tin theme về sau đó vào phân theme của word để cài bằng cách tải tập tin zip lên. Trên là 9 bước cơ bản để xây dựng một website Wordpress sạch.","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Wordpress","slug":"Wordpress","permalink":"http://nguyenvantien2009.com/tags/Wordpress/"},{"name":"Blog","slug":"Blog","permalink":"http://nguyenvantien2009.com/tags/Blog/"},{"name":"Wordpress Theme","slug":"Wordpress-Theme","permalink":"http://nguyenvantien2009.com/tags/Wordpress-Theme/"}],"author":"Tiển Nguyễn"},{"title":"Install PoS Box of Odoo in Raspberry 3 B+","slug":"2021/install-pos-box-odoo-in-rasphberry-3-b+","date":"2020-02-19T17:00:00.000Z","updated":"2022-06-02T08:48:38.556Z","comments":true,"path":"2021/install-pos-box-odoo-in-rasphberry-3-b+.html","link":"","permalink":"http://nguyenvantien2009.com/2021/install-pos-box-odoo-in-rasphberry-3-b+.html","excerpt":"","text":"Install PoS Box of Odoo in Raspberry 3 B+Date: 209-07-16 by Tien Nguyen AbstractPOSBox is good device be used in Poin of Sale in Odoo. It help we connect to many device of POS as printer, cash, scanner… If you install Odoo to PC is POSBox is not may benefit. But if you use PoS Odoo in Cloud by access application in browser, POSBox is a device help connect other devices in shop. We write poxbox image provided by Odoo. Then plug mirco card was written to Raspberry. Now Raspberry as POSBox that we can use connect to other devices. 1. Prepare Device & Software1.1 Devices Raspberry 3 B+ (prices ~ 50-59 USD) Adapter for Raspberry (We can use other adapter if have port for micro usb) Micro Memory Card & Reader Micro Memory Card HDMI Cable to connect to Monitor 1.2 Software POSBox Image - v12, 13 (download from https://nightly.odoo.com/trunk/posbox/) Win32DiskImag (use to write POSBox Image to Micro Memomory Card) 2. Install POSBox Image to Raspberry Unzip POSBOX image downloaded and change file name with subfix .img. Open Win32DiskImager to write image to micro card. Push micro card to Raspberry 3 B+ to test result. 3. Setting POSBox Image connect to Odoo POSBoxWhen open POSBOX in Raspberry. It unstill connect to POS Odoo. We need need use other PC (PC or Laptop) to setting. Run Odoo POS in Laptop and connect wifi to PoS Image. Click wifi icon, we will see wifi have name is PoS Image. After connect to PoS Image, we access to PoS Odoo from IP show in PoSBox (We will see this IP when connect Raspberry with a monitor). Find and Click connect wifi link then fill pass of wifi. Now we need restart Raspberry to apply new setting. After restart we will see IP in Raspberry show with LAN IP address. And we use this IP to setting in POS Odoo. Access POS Odoo. Choose POSBox Setting to enable PoS Box. Enter IP address that we see in Raspberry. 4. TestingNow setting is done. We need plug printer, scanner, cash… to Raspberry with USB port. Then use feature of POS Box.","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"PoS","slug":"PoS","permalink":"http://nguyenvantien2009.com/tags/PoS/"},{"name":"PoS Box","slug":"PoS-Box","permalink":"http://nguyenvantien2009.com/tags/PoS-Box/"},{"name":"Raspberry","slug":"Raspberry","permalink":"http://nguyenvantien2009.com/tags/Raspberry/"},{"name":"Odoo","slug":"Odoo","permalink":"http://nguyenvantien2009.com/tags/Odoo/"}],"author":"Tiển Nguyễn"},{"title":"CI and CD in Gitlab","slug":"2021/ci-and-cd-in-gitlab","date":"2020-02-14T17:00:00.000Z","updated":"2022-06-02T09:08:21.078Z","comments":true,"path":"2021/ci-and-cd-in-gitlab.html","link":"","permalink":"http://nguyenvantien2009.com/2021/ci-and-cd-in-gitlab.html","excerpt":"","text":"PipelineJobSchedulerChartPreferences","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"Gitlab","slug":"Gitlab","permalink":"http://nguyenvantien2009.com/tags/Gitlab/"},{"name":"CI/CD","slug":"CI-CD","permalink":"http://nguyenvantien2009.com/tags/CI-CD/"},{"name":"Process","slug":"Process","permalink":"http://nguyenvantien2009.com/tags/Process/"}],"author":"Tien Nguyen"},{"title":"Create Dockerfile for HapiJS","slug":"2021/create-dockerfile-for-hapijs","date":"2020-02-09T17:00:00.000Z","updated":"2022-06-02T08:34:14.123Z","comments":true,"path":"2021/create-dockerfile-for-hapijs.html","link":"","permalink":"http://nguyenvantien2009.com/2021/create-dockerfile-for-hapijs.html","excerpt":"","text":"Dockerfile cho máy chủ chạy dự án HapiJS Dockerfile for VTS ID.123456789101112131415161718192021FROM centosENV ID_SOURCE_DIR=/vts-id# Install Node.js and npmRUN apt-get update && \\ && apt-get install -y curlRUN curl -sL https://deb.nodesource.com/setup_11.x | bash - \\ && apt-get install -y nodejs \\ && apt-get install -y git# Pull Auth Service.RUN git clone --depth=1 -b ${ID_BRAND} http://${GIT_USER}:${GIT_PASS}@gitlab.vtsspace.com/vts-service/vts-id.git ${ID_SOURCE_DIR}# Install app dependenciesRUN cd ${ID_SOURCE_DIR} && \\ npm installEXPOSE 80CMD ["npm", "${ID_SOURCE_DIR}/bootstrap.js"]","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Docker","slug":"Docker","permalink":"http://nguyenvantien2009.com/tags/Docker/"},{"name":"HapiJS","slug":"HapiJS","permalink":"http://nguyenvantien2009.com/tags/HapiJS/"},{"name":"Restful","slug":"Restful","permalink":"http://nguyenvantien2009.com/tags/Restful/"},{"name":"Deployment","slug":"Deployment","permalink":"http://nguyenvantien2009.com/tags/Deployment/"}],"author":"Tien Nguyen"},{"title":"Thiết Lập Máy Chủ Chạy Hapi.js","slug":"2021/hapijs-server-configuration-fo-services","date":"2020-01-17T17:00:00.000Z","updated":"2022-06-02T08:36:51.461Z","comments":true,"path":"2021/hapijs-server-configuration-fo-services.html","link":"","permalink":"http://nguyenvantien2009.com/2021/hapijs-server-configuration-fo-services.html","excerpt":"","text":"Thiết lập máy chủ chạy Hapi.js Cài đặt NodeJS và NPMTải dự án HapiJS sau đó chạy thửCài đặt và cấu hình NGINXCài đặt và cấu hình PM2PM2 là công cụ giúp triển khai các dự án web trên nền tảng NodeJS. Nó giúp ta có thể thao tác quản lý web server ở dạng dòng lệnh. Đặc biệt nó sẽ hỗ trợ cho các server web giảm đi downtime khi triển khai. Bên cạnh đó nó còn hỗ trợ tính năng load balancing giúp giảm tải các máy chủ. 123456# Install PM2 in global state.sudo npm install pm2 -g# Start run index.js (code start web server in here) wiht name `site`.pm2 start index.js --name site# Show log of site (`site` is name start by pm2).pm2 logs site --line # show log data with multilines.","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"HapiJS","slug":"HapiJS","permalink":"http://nguyenvantien2009.com/tags/HapiJS/"},{"name":"Deployment","slug":"Deployment","permalink":"http://nguyenvantien2009.com/tags/Deployment/"},{"name":"Server","slug":"Server","permalink":"http://nguyenvantien2009.com/tags/Server/"},{"name":"NodeJS","slug":"NodeJS","permalink":"http://nguyenvantien2009.com/tags/NodeJS/"},{"name":"Load Balancing","slug":"Load-Balancing","permalink":"http://nguyenvantien2009.com/tags/Load-Balancing/"},{"name":"PM2","slug":"PM2","permalink":"http://nguyenvantien2009.com/tags/PM2/"}],"author":"Tiển Nguyễn"},{"title":"Install MongoDB in Docker","slug":"2021/install-mongo-db-by-docker","date":"2020-01-12T17:00:00.000Z","updated":"2022-06-02T08:48:14.059Z","comments":true,"path":"2021/install-mongo-db-by-docker.html","link":"","permalink":"http://nguyenvantien2009.com/2021/install-mongo-db-by-docker.html","excerpt":"","text":"Những điểm cần lưu ý khi cài đặt MongoDB bằng Docker là: Sau khi chạy một câu lệnh để lấy về và chạy từ docker image thì chưa thể truy cập từ bên ngoài (tức chỉ có thể truy cập bằng localhost). Cần thực hiện thêm một bước tạo tài khoản và cho phép nó có thể đăng nhập từ bên ngoài. 1. Tải và chạy MongoDB từ Docker Image123456docker run --name hd-mongo \\ -e MONGO_INITDB_ROOT_USERNAME="mongdb.admin" \\ -e MONGO_INITDB_ROOT_PASSWORD="admin" \\ -v /data/mongdb:/data/db \\ -p 27017:2707 \\ -d mongo Nhưng chúng ta nên dùng docker compose để thuận tiện hơn cho việc chỉnh sửa trong tương lai. 123456789101112131415161718version: '3.3'services: mongo: image: mongo:latest environment: MONGO_INITDB_ROOT_PASSWORD: password MONGO_INITDB_ROOT_USERNAME: username ports: - 27017:27017 volumes: - /data/mongdb:/data/db networks: - docker_mongo logging: driver: json-filenetworks: docker_mongo: driver: overlay 2. Tạo tài khoản sau đó cho phép quyền truy cập1234567891011mongouse amdin # switch database to admin database# create a new user with role. # if see message role is not exists. can create new account wth array of rolde# is emaptydb.createUser({user: "admin", pwd: "password", \\ roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]})exit;mongod stopmongod --auth --port 27017 # option `--auth` will help required login.","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"Docker","slug":"Docker","permalink":"http://nguyenvantien2009.com/tags/Docker/"},{"name":"MongoDB","slug":"MongoDB","permalink":"http://nguyenvantien2009.com/tags/MongoDB/"},{"name":"Install","slug":"Install","permalink":"http://nguyenvantien2009.com/tags/Install/"},{"name":"Databases","slug":"Databases","permalink":"http://nguyenvantien2009.com/tags/Databases/"}],"author":"Tien Nguyen"},{"title":"Sao Lưu Và Phục Hồi Một Docker Image","slug":"2021/backup-and-restore-docker-container","date":"2019-12-26T05:00:00.000Z","updated":"2022-06-02T08:29:52.104Z","comments":true,"path":"2021/backup-and-restore-docker-container.html","link":"","permalink":"http://nguyenvantien2009.com/2021/backup-and-restore-docker-container.html","excerpt":"","text":"Công cụ1npm i -g docker-backup Tạo cấu trúc sao lưuTrước khi tạo bản sao lưu ta cần tạo một cấu trúc dễ hiểu. Mục tiêu là có thể nhìn vào là thấy ngay bản sao lưu của ứng dụng gì và thời gian sao lưu là khi nào. Thỉnh thoảng có thể thêm phiên bản nhưng đối với các dự án nhỏ thì chưa cần thêm thông số này. 1mkdir -pw -m 775 /docker-backup/{app-name}/{app-name}-{%Y-%m-%d-%H%m%s}/* Trên là cấu trúc thư mục trên mỗi phiên bản sao lưu. Riêng với các máy chủ sao chép bản sao ưu cần có thểm server-name. Tên của máy chủ sẽ được gán trong hệ thống. 12mkdir -pw -m 775 /{server-name}/docker-backup/{app-name}/ \\ {app-name}-{%Y-%m-%d-%H%m%s}/* 1. Sao lưuNhư đã đề cập trên. Chúng tôi sẽ sử dụng docker-backup để sao lưu. 1.1. Sao lưu123docker-backup {container-name} {backup-path} --name {new name backup}# Ex:docker-backup ghost-backup /backups --name ghost-backup-2019-12-21-122311 Sau khi chạy dòng lệnh trên bạn sẽ thấy được 3 tập tin chính là image, create (script tạo docker container), volumes. 1.2. Nén thư mục sao lưuPhiên bản backup thường được nén để giảm độ lớn của dung lượng lưu trữ. 1zip -r backups.zip /backups 1.3. Chuyển tập tin sao lưu sang máy chủ khácChúng tôi sử dụng rsync để chuyển các tập tin từ máy tính này sang máy tính khác. Cần cài đặt rsync trước khi thực hiện. Nếu máy tính bạn đã được cài đặt thì có thể bỏ qua bước này. 1apt install rsync Bây giờ có thể chuyển tập tin hoặc thư mục sang máy tính khác thông qua dòng lệnh sau: 1rsync -r /backup/. root@45.119.215.100:/backups/SVR.DEV.01 Trong đoạn mã trên tôi đã chuyển toàn bộ nội dung có trong thư mục /backup/ bằng cách sử dụng tùy chọn -r. 2. Phục hồi2.1. Vận chuyểnTa cần chuyển từ server khác về server hiện tại để có thể 1rsync -r root@45.119.215.100:/backups/SVR.DEV.01 /backup/. 2.2. Giải nénCần đảm bảo ứng dụng unzip cần được cài đặt trên máy tính. 1apt install unzip Đây là câu lệnh có thể sử dụng để có thể unzip. 1unzip filename.zip -d /folder/filename 2.3 Phục hồiĐể phục hồi được phiên bản docker chúng ta cần phải đảm bảo được 3 tập tinimage, create và volume. 1234docker-backup restore /backups/ghost-backup_image.tardocker-backup restore /backups/ghost-backup_create.shdocker-backup restore /backups/ghost-backup_volume_xx.tar ghost-backupdocker start ghost-backup Chúng ta cần thực hiện 4 bước để có thể phục hồi một docker container. Phục hồi image, create, volume và cuối cùng là chạy Docker đó. Ví dụĐoạn mã dưới đây là ví dụ giúp tôi có thể tạo một bản sao lưu của Docker Container với tên là some-ghost. 123456docker run --name some-ghost -p 8080:2368 -d ghostdocker-backup some-ghost /backups --name ghost-backupdocker-backup restore /backups/ghost-backup_image.tardocker-backup restore /backups/ghost-backup_create.shdocker-backup restore /backups/ghost-backup_volume_xx.tar ghost-backupdocker start ghost-backup Sẽ có tập tin được sinh ra sau khi chạy đoạn mã trên tương ứng với image, script để tạo lại docker container và volumes. Sau khi bản sao được tạo. Ta có thể dùng thêm đoạn mã để nén tập tin vừa tạo nhằm giảm dung lượng lưu trữ và thuận tiện cho việc vận chuyển sang nơi chứa khác nếu cần. 1zip -r backups.zip /backups Tài liệu tham khảo https://github.com/soenkekluth/docker-backup","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"Docker","slug":"Docker","permalink":"http://nguyenvantien2009.com/tags/Docker/"},{"name":"Backup Restore","slug":"Backup-Restore","permalink":"http://nguyenvantien2009.com/tags/Backup-Restore/"}],"author":"Tiển Nguyễn"},{"title":"Cross-Domain (CORS) With Restful API in Laravel","slug":"2021/crossdomain-CORS-with-restful-api-in-laravel","date":"2019-12-10T17:00:00.000Z","updated":"2022-06-02T08:35:13.067Z","comments":true,"path":"2021/crossdomain-CORS-with-restful-api-in-laravel.html","link":"","permalink":"http://nguyenvantien2009.com/2021/crossdomain-CORS-with-restful-api-in-laravel.html","excerpt":"","text":"Cross-domain (CORS) with Restful API in LaravelToday, most web projects are developed based on the client-server model. The web client (Web UI) will call the server through the Restful service. When we invoke the API from a browser, we will experience cross domain issues because browsers have security mechanisms. We cannot call the API if the API domain name is not the same as the WebUI domain. Solution 1: Use proxy to Client the same domain for servicesEach service has a unique address. May be different in domain or just different in port on address of service. In a secure manner web browsers do not allow them to call each other without permission from the calling service. To solve this, we need to use an intermediary app to help them talk to each other. In this article, I will use nginx as a proxy for communication services. 12apt updateapt install nginx After nginx installed success. We need new file host in /etc/nginx/sites-available/nguyenvantien2009.com. With nguyenvantien2009.com is a domain that we need build for website. It will present in server_name attribute in under code block. 1234567891011121314151617# file: \\etc\\nginx\\sites-available\\nguyenvantien2009.comserver { listen 80; server_name nguyenvantien2009.com; access_log /var/log/nginx/reverse-access.log; error_log /var/log/nginx/reverse-error.log; location /api { proxy_pass http://127.0.0.1:8001; } location / { proxy_pass http://127.0.0.1:8000; }} We have 2 proxy used in code block: http://127.0.0.1:8001 and http://127.0.0.1:8000. They appied when user call address http://nguyenvantien2009.com/api and http://nguyenvantien2009.com/api. Now you has not yet use this config in nginx. We need symbolic link file file to site-enable folder. You need run under code. 123cd /etc/nginx/site-enableln -s ../sites-available/nguyenvantien2009.comservice nginx restart Solution 2: Allow calls from any address in the service to be calledThis is a quick but non-secure solution. We should only use it during development. It does not need many to setup steps. With PHP, we just add code block related to the header of response from the result returned in a request enought to solve the problem. 123header("Access-Control-Allow-Origin: *");header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');header('Access-Control-Allow-Headers', 'Accept, X-Requested-With, Content-Type, X-Token-Auth, Authorization'); But for the Laravel we have a more professional way. Laravel’s middleware help you do this. What we need to do is create new middleware for CORs to apply APIs that we want. Those are steps we need. 1. Create CORs MiddlewareWe can use command line create Cors middleware. After Cors is create, it is contained in app/Http/Middleware/Cors.php. 1php artisan make:middleware Cors We implement code for this class. Headers Information added to request of HTTP. 1234567891011121314// file: app\\Http\\Middleware\\Cors.phpnamespace App\\Http\\Middleware;use Closure;class Cors { public function handle($request, Closure $next) { return $next($request) ->header('Access-Control-Allow-Origin', '*') ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS') ->header('Access-Control-Allow-Headers', 'Accept, X-Requested-With, Content-Type, X-Token-Auth, Authorization'); }} 2. Add CORs Middleware to KernelAfter Cors created. It has not yet been used in the API. We need tell to Laravel to load it via Kernel. Go to app/Http/Kernel.php to declare it. Here are three places where middleware can be used: global, group and route. Corresponding to these 3 positions you have $middleware, $middlewareGroups and $routeMiddleware. If it is global it will be used in all requests to your service. However, if you only want it to be used in specific API groups then group will help you. For example, you need to check for a certain condition when calling the API under decentralized. The other is route, which assigns to each specific API you want in app/routes/api.php. This is code block that we want use CORs middleware for all request. 123456789101112131415// file: app\\Http\\Kernel.php... class Kernel extends HttpKernel { 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, \\App\\Http\\Middleware\\Cors::class, ]; ...} 3. Apply for APIsAs you know. If you load Cors for global score, you no need this step. But if you want aply Cors for group or route, you need this step. 1234567891011// file: app\\routes\\api.phpRoute::group(['middleware' => 'cors'], function () { Route::post('login', 'Api\\UserController@login'); Route::post('register', 'Api\\UserController@register');});Route::group(['middleware' => ['auth:api', 'cors']], function () { Route::get('user/info', 'Api\\UserController@info'); Route::get('product', 'Product\\ProductController@list');}); We have 2 groups. A group no-need login and a group need login. Both groups need use Cors middleware for request. We need add cors in Route::group. Noted: you need declare Cors middleware in $middlewareGroups from app/Http/kernel.php. Reference https://medium.com/@dtkatz/3-ways-to-fix-the-cors-error-and-how-access-control-allow-origin-works-d97d55946d9","categories":[{"name":"Lập trình","slug":"Lap-trinh","permalink":"http://nguyenvantien2009.com/categories/Lap-trinh/"}],"tags":[{"name":"Restful","slug":"Restful","permalink":"http://nguyenvantien2009.com/tags/Restful/"},{"name":"PHP","slug":"PHP","permalink":"http://nguyenvantien2009.com/tags/PHP/"},{"name":"Laravel","slug":"Laravel","permalink":"http://nguyenvantien2009.com/tags/Laravel/"},{"name":"CORS","slug":"CORS","permalink":"http://nguyenvantien2009.com/tags/CORS/"}],"author":"Tien Nguyen"},{"title":"Crontab Command Line in Ubuntu","slug":"2021/crontab-in-ubuntu-command-line","date":"2019-12-07T06:28:00.000Z","updated":"2022-06-02T08:34:59.145Z","comments":true,"path":"2021/crontab-in-ubuntu-command-line.html","link":"","permalink":"http://nguyenvantien2009.com/2021/crontab-in-ubuntu-command-line.html","excerpt":"","text":"Crontab là công cụ chúng ta nói cho máy chủ Linux thực hiện một lệnh nào đó theo lịch định. Lệnh được thực hiện là một lệnh đơn giản hoặc một khối lệnh. Crontab cũng cho ta xem lịch sử thực hiện các khối lệnh thông qua log của chính nó đã được lưu. Bài viết này sẽ liệt kê các lệnh thường được dùng phổ biến trong crontab. Trước tiên tìm hiểu các lệnh ta cần phải hiểu được cấu trúc lịch được định nghĩa trong crontab. Cấu trúc Lịch12345678* * * * * YOURCOMMAND- - - - -| | | | || | | | +----- Day in Week (0 to 7) (Sunday is 0 and 7)| | | +------- Month (1 to 12)| | +--------- Day in Month (1 to 31)| +----------- Hour (0 to 23)+------------- Minute (0 to 59) Hình ảnh trên giúp ta thấy rõ cấu trúc lịch của một crontab (hình ảnh được sưu tầm trên Internet). Dưới đây sẽ mô tả thêm ý nghĩa của 5 dấu *. Đơn vị nhỏ nhất của nó là phút và lớn nhất là tháng được tín từ dấu * thứ 1 đến thứ 4. Riêng dấu * cuối cùng chỉ thứ trong tuần. Nó hỗ trợ cho các lịch chỉ thực hiện theo thứ trong tuần. Rất có ích khi chỉ thực hiện lệnh ta muốn cho chủ nhật hoặc thứ 7. Đối với phút, giờ và thứ trong tuần được bắt đầu bằng số 0. Vì nó thể hiện một vị trí nào đó dạng Index. Còn ngày và tháng thì được bắt đầu bằng số 1. Đối với năm sẽ không tồn tại trong lịch. Có thể quá ít trường hợp sử dụng nên người tạo ra đã không cần thêm vào. Nếu ta dùng một số cụ thể để thiết lập lịch thì hệ thống chỉ thực hiện khi đến một lịch cụ thể. Ví dụ 2 * * * * chỉ thực thi ở phút thức 2. Tức là một giờ chỉ thực hiện 1 lần vì chỉ có 1 lần phút là 2. Nhưng nếu cần thực hiện mỗi 2 phút 1 lần thì cần phải khai báo */2 * * * *. Nó có thể hiểu là chia hết thì mới thực hiện. Cấu trúc lệnh tổng quátCrontab sẽ được các dòng lệnh vào một tập tin (file) nào đó với phân quyền của tài khoản trong hệ điều hành (user). Chúng ta có thể mở một tập tin cụ thể trong crontab để thao tác nào đó. 1crontab [-u user] file Nó chia làm 4 thư mục để quản lý theo chu kỳ thực hiện. hourly, daily, weekly, monthly. Và được lưu cụ thể trong các thư mục bắt đầu bằng cron. như cron.daily, cron.weekly… Các lịch này thường là các tập tin được thêm từ các ứng dụng cài đặt bên ngoài. Do đó nếu bạn thêm lịch thực thi từ crontab -e thì sẽ không thấy trong đây. Do đó nó chỉ hữu dụng khi ta viết ứng dụng có sử dụng lịch để thực hiện một công việc nào đó. 1crontab [-u user] [-l | -r | -e] [-i] [-s] Tiếp đến là cấu trúc câu lệnh mà ta có thể thực hiện khi tương tác đến crontab. Hãy tìm hiểu các tham số được thêm vào câu lệnh trên. Tham số Ý nghĩa -l Hiện thị các crontab hiện tại -r Xóa một crontab hiện tại -e Soạn thảo thêm/ xóa crontab -i Xóa một crobtab hiện tại. Giống -r nhưng sẽ hỏi lại người dùng trước khi xóa Nơi lưu trữ LịchNhư đã đề cập bên trên. Ngoài các tập tin được chứa trong /etc/cron.*, các crontab cũng được chứa trong /var/spool/ mỗi khi ta dùng crontab -e. Cụ thể là /var/spool/cron/crontabs/root nếu ta đang dùng tài khoảng root để thêm crontab. Tuy nhiên, chúng ta không được phép thêm, xóa, sửa trong đây mà phải thông qua crontab -e để cập nhật một crontab. Lệnh phổ biến12345678910crontab -e # open editor crontabcrontab -u charles -e # editor crontab for user charlescrontab -l # list current crontabcrontab -r # remove crontab# execute `.sh` follow scheduler15 6 2 1 * /home/melissa/backup.sh # run script at 9h and 18h.0 9,18 * * Mon /home/wendy/script.sh Kết luậnBài viết đã liệt đủ những điều kiện cần thiết khi ta muốn thực hiện một công việc nào đó tự động theo một lịch trình định sẳn. Đây cũng được xem là một công cụ tự động thần kỳ nếu ta biết tận dụng triệt để trong các ứng dụng của mình. Mặc dù các ngôn ngữ lập trình đã hỗ trợ lịch trình nhưng có các lệnh chỉ tương tác đến hệ thống như đẩy trạng thái của máy tính đang chạy đến một máy khác một cách tự động theo lịch trình thì thực hiện ở crontab sẽ thuận tiện và nhanh chóng.","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"Server","slug":"Server","permalink":"http://nguyenvantien2009.com/tags/Server/"},{"name":"Ubuntu","slug":"Ubuntu","permalink":"http://nguyenvantien2009.com/tags/Ubuntu/"},{"name":"Crontab","slug":"Crontab","permalink":"http://nguyenvantien2009.com/tags/Crontab/"}],"author":"Neit Ng"},{"title":"Syspass Help to Storage Services's Password","slug":"2021/syspass-help-storage-password-for-services","date":"2019-12-06T17:00:00.000Z","updated":"2022-06-02T09:02:54.737Z","comments":true,"path":"2021/syspass-help-storage-password-for-services.html","link":"","permalink":"http://nguyenvantien2009.com/2021/syspass-help-storage-password-for-services.html","excerpt":"","text":"Nếu bạn xây dựng một công ty thì sẽ có nhiều dịch vụ cần có thông tin tài khoản riêng. Chúng ta không thể nhớ hết các tài khoản nó. Do đó thường ghi ra ở một nơi nào đó. Nhưng nếu ghi ra thì đã vi phạm tín bảo mật của mật khẩu. sysPass là một mã nguồn mở giúp ta có thể mã hóa các mật khẩu của mình được xây dựng trên nền tảng web nên có thể chia sẽ lẫn nhau trong nhóm mà vẫn an toàn. Giới thiệu sysPassChúng ta có thể dễ dàng tìm với từ khóa syspass sau đó tải về từ github. Đây là trang web chính thức của syspass https://www.syspass.org/en. Chúng ta có thể đọc thêm thông tin hướng dẫn từ https://readthedocs.org/projects/syspass-doc/downloads/pdf/3.0/. Nếu bạn cần thêm thông tin từ hướng dẫn có thể xem đường dẫn https://doc.syspass.org/en/3.1/. Chúng ta hãy cẩn thận khi sử dụng phần mền để lưu các mật khẩu của các dịch vụ. Nếu mã nguồn không đáng tin cậy sẽ mất hết mật khẩu và điều đó là một thảm họa. Mất các mật khẩu là mất tài sản thông tin và có thể ảnh hưởng dây chuyền đến các dịch vụ khác. Cần chú ý đến đường dẫn trong Github để tránh các trường hợp giả mạo. Đây là đường dẫn chính thức https://github.com/nuxsmin/docker-syspass. Dưới đây là các tính năng đáng chú ý về bảo mật: Mã hóa mật khẩu AES-256 Sử dụng cơ sở dữ liệu MySQL/ MariaDB, OpenLDAP và Active Directory. Ghi lại lịch sử sử dụng người dùng. Tạo một bản sao lưu dưới dạng nhiều định dạng XML, JSON… API để tích hợp với các ứng dụng khác. Sử dụng *.csv để có thể tạo lại cơ sở dữ liệu. Cài đặt sysPasssysPass được xây dựng trên ngôn ngữ PHP. Do đó để chạy được nó máy tính bạn cần phải có Apache (hay một web server có thể chạy PHP nào đó), MySQL và PHP. Nhưng sysPass cũng hỗ trợ chúng ta cài đặt trên môi trường Docker. Trong đây cũng có 2 sự lựa chọn: Cài đặt các Docker Container riêng lẻ sysPass và MySQL hay có thể sử dụng Docker Compose để chạy đặt một lần cho 2 Docker Container trên. Cài đặt với Docker ComposeNếu bạn chưa có cơ sở dữ liệu thì có thể sử dụng Docker Compose để cài đặt cho sysPass và MySQL đồng thời. 123456789101112131415161718192021222324252627282930313233# file: docker-compose.ymlversion: '2'services: app: container_name: syspass-app image: syspass/syspass:3.1.0 restart: always ports: - "80" - "443" links: - db volumes: - syspass-config:/var/www/html/sysPass/app/config - syspass-backup:/var/www/html/sysPass/app/backup environment: - USE_SSL=yes db: container_name: syspass-db restart: always image: mariadb:10.2 environment: - MYSQL_ROOT_PASSWORD=syspass ports: - "3306" volumes: - syspass-db:/var/lib/mysqlvolumes: syspass-config: {} syspass-backup: {} syspass-db: {} Cài đặt với Docker Containers Ở phần này tôi sẽ không đề cập đến MySQL vì nó đã đơn giản và được viết bởi nhiều bài viết. Nên đến phần này tôi đã giả sử máy tính của bạn đã được cài đặt MySQL. 1234567docker run -d --name syspass-vts \\ -p 80:80 \\ -p 443:443 \\ -v /config/syspass:/var/www/html/sysPass/app/config \\ -v /backup/syspass:/var/www/html/sysPass/app/backup \\ -e USE_SSL=yes \\ syspass/syspass Tôi đã sử dụng đoạn mã trên để cài đặt sysPass dưới dạng Docker. Bạn có thể chạy trang web với cổng 80 và 443. Nhưng thường nên dùng SSL để các đường truyền của bạn được bảo mật hơn. Bên cạnh đó chúng tôi cũng muốn liên kết các thư mục của tập tin cấu hình và sao lưu lên máy tính vật lý thông qua 2 -v được thể hiện trong đoạn mã. Sau khi được cài đặt thành công. Chúng ta có thể chạy đường dẫn https://localhost (Lưu ý: trong đường dẫn nên là SSL với https://). để có thể khai báo các thông tin liên quan để kết nối đến cơ sở dữ liệu. Dockerfile123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687## https://syspass.org# https://doc.syspass.org#FROM composer:1.7 as bootstrapENV SYSPASS_BRANCH="master"RUN git clone --branch ${SYSPASS_BRANCH} https://github.com/nuxsmin/sysPass.git \\ && composer install \\ --ignore-platform-reqs \\ --no-interaction \\ --no-plugins \\ --no-scripts \\ --prefer-dist \\ --no-dev \\ --classmap-authoritative \\ --working-dir /app/sysPassFROM debian:stretch as appLABEL maintainer=nuxsmin@syspass.org version=3.1.0 php=7.0 environment=productionRUN apt-get update \\ && DEBIAN_FRONTEND=noninteractive apt-get -y install \\ locales \\ apache2 \\ libapache2-mod-php7.0 \\ php-pear \\ php7.0 \\ php7.0-cgi \\ php7.0-cli \\ php7.0-common \\ php7.0-fpm \\ php7.0-gd \\ php7.0-json \\ php7.0-mysql \\ php7.0-readline \\ php7.0-curl \\ php7.0-intl \\ php7.0-ldap \\ php7.0-mcrypt \\ php7.0-xml \\ php7.0-mbstring \\ git \\ gosu \\ unzip \\ && apt-get clean \\ && rm -r /var/lib/apt/lists/*ENV APACHE_RUN_USER="www-data" \\ APACHE_RUN_GROUP="www-data" \\ APACHE_LOG_DIR="/var/log/apache2" \\ APACHE_LOCK_DIR="/var/lock/apache2" \\ APACHE_PID_FILE="/var/run/apache2.pid" \\ SYSPASS_DIR="/var/www/html/sysPass" \\ SYSPASS_UID=9001WORKDIR /var/www/htmlLABEL build=19081801# Custom sysPass Apache config with SSL by defaultCOPY ["syspass.conf", "/etc/apache2/sites-available/"]# Custom entrypointCOPY entrypoint.sh init-functions /usr/local/sbin/RUN chmod 755 /usr/local/sbin/entrypoint.sh \\ && a2dissite 000-default default-ssl \\ && a2ensite syspass \\ && a2enmod proxy_fcgi setenvif ssl rewrite \\ && a2enconf php7.0-fpm \\ && ln -sf /dev/stdout ${APACHE_LOG_DIR}/access.log \\ && ln -sf /dev/stderr ${APACHE_LOG_DIR}/error.log# sysPass dependenciesCOPY --from=bootstrap /app/sysPass/ ${SYSPASS_DIR}/# Composer binaryCOPY --from=bootstrap /usr/bin/composer /usr/bin/EXPOSE 80 443ENTRYPOINT ["/usr/local/sbin/entrypoint.sh"]CMD ["apache"] Sao lưu và giải mã mật khẩusysPass có thể sao lưu từ ứng dụng sau đó đưa lên đĩa tại thư mục /var/www/html/sysPass/app/backup và trong đoạn mã trên sẽ được liên kết đến thư mục /backup/syspass. Trong ứng dụng cũng cho phép bạn tải các tập tin đó về để lưu vào trong máy tính cá nhân nhưng vẫn ở chế độ mã hóa nên không thể bị mất cắp. Mật khẩu được lưu trong MySQL điều được sysPass mã hóa với giải thuật ASE-256. Do đó khi lấy được thông tin từ cơ sở dữ liệu vẫn không thể biết được mật khẩu là gì. Điều này cũng xẫy ra với các tập tin đã được tải về máy tính cá nhân. Chúng tôi phải sử dụng https://gitlab.com/MagicFab/sysPass-XML-Decrypter để có thể đọc được thông tin đưới dạng văn bản. 12345git clone https://gitlab.com/MagicFab/sysPass-XML-Decrypter.gitcd sysPass-XML-Decryptercomposer install ./decrypt.php <path-to-encrypted-xml> \\ <xml-export-password> <syspass-master-password> \\ <dest-file> [format] [format] là keepass hay lastpass. Nếu không khai báo thông tin cho tham số format thì nó sẽ lấy keepass. Tài liệu tham khảo Docker Compose trên Github https://github.com/nuxsmin/docker-syspass Docker sysPass trên Docker Hub https://hub.docker.com/r/syspass/syspass docker-compose.yml https://github.com/nuxsmin/docker-syspass/blob/master/docker-compose.yml","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Server","slug":"Server","permalink":"http://nguyenvantien2009.com/tags/Server/"},{"name":"Ubuntu","slug":"Ubuntu","permalink":"http://nguyenvantien2009.com/tags/Ubuntu/"},{"name":"Password","slug":"Password","permalink":"http://nguyenvantien2009.com/tags/Password/"},{"name":"Syspass","slug":"Syspass","permalink":"http://nguyenvantien2009.com/tags/Syspass/"}],"author":"Neit Ng"},{"title":"Cài đặT Redis Với Docker","slug":"2021/install-redis-by-docker","date":"2019-12-02T17:00:00.000Z","updated":"2022-06-02T08:49:00.183Z","comments":true,"path":"2021/install-redis-by-docker.html","link":"","permalink":"http://nguyenvantien2009.com/2021/install-redis-by-docker.html","excerpt":"","text":"Redis được sử dụng nhiều khi ta cần một cơ sở dữ liệu dạng bộ nhớ. Hầu hết các ứng dụng ngày nay điều sử dụng nó như là một bộ nhớ tạm trong các hệ thống liên máy chủ cụ thể là các dịch vụ theo mô hình Micro-Service Chúng ta cần ít nhất 3 bước để có thể cài đặt Redis với Docker. 1. Cài đặt với Docker Redis ServerChúng ta cần tải Docker Image của Redis về máy tính để có thể chạy được. Docker Image của Redis đang được đặt tại Redis Hub. 1docker pull redis Bây giờ tiến hành chạy Redis Container. Khi thực hiện đoạn mã dưới nếu bạn chưa tải về Redis Image sẽ được tự động tải về. 12345docker run \\ -p 6379:6379 \\ -v /data/redis:/data \\ --name redis_truststore \\ -d redis --appendonly yes --requirepass "ZtH6rZYW" Đoạn mã trên đồng nghĩa với chạy Redis với cổng 6379 và dữ liệu sẽ được lưu tại máy tính vật lý (máy tính thật đang chạy Docker Redis) theo đường dẫn /data/redis. Mọi dữ liệu trong /data của Docker Container sẽ được chứa tại /data/redis. Khi kết nói đến Redis bạn sẽ bị yêu cầu mật khẩu là ZtH6rZYW. Ghi chú: chúng tôi đã dùng dấu ' không thành công cho mật khẩu do đó tôi đã đổi sang ". 2. Cài đặt Redis ClientĐược sử dụng để kết nối đế Redis Server. Tùy vào máy tính của bạn đang sử dụng hệ điều hành nào thì bạn cần cài ứng dụng client tương ứng. Trong bài viết tôi đang dùng Window nên cần phải dùng https://github.com/microsoftarchive/redis/releases/tag/win-2.8.2104. Sau khi tải về cần giải nén và thiết lập biến môi trường trong Window để dễ dàng sử dụng lệnh trong các giao diện Console của Window. 1redis-cli -h 100.1.20.1 -p 6379 -a "ZtH6rZYW" Câu lệnh trên sẽ giúp bạn kết nối Redis tại server có IP là 100.1.20.1 thông qua cổng 6379 và dùng mật khẩu ZtH6rZYW để xác thực. Mật khẩu này do bạn đã thiết lập trong quá trình chạy Docker ở phần [1.]. 3. Thiết lập Domain trên LocalNếu bạn kết nối bằng địa chỉ IP thì khá bất tiện. Để dễ dàng nhớ hơn ta có thể vào ~/hosts để thiết lập một domain trở đến IP đó. 1100.1.20.1 redis.nguyenvantien.com Bây giờ có thể thay thế địa chỉ IP trong câu lệnh kết nối bằng domain mới vừa tạo ấy. 4. Thiết lập Domain trên OnlineNếu bạn đang làm việc nhóm thì bước này khá cần thiết để nhóm có thể kết nối thông qua một domain online. Với domain này bạn phải trả tiền và vào phần quản lý của domain để thiết lập giúp domain trỏ đến địa chỉ IP mà bạn đang chứa Redis Server. 5. Kết luậnHãy sử dụng Redis Docker để cài đặt nhanh chống Redis Server và sử dụng Redis Client kết nối. Bạn có thể không cần phải nhớ địa chỉ IP của Redis Server nếu thiết lập một domain để trỏ đến địa chỉ đó bằng domain giải lập (thiết lập ở ~/hosts trên máy tính cá nhân) hoặc domain online (mua bởi các nhà cung cấp domain).","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Docker","slug":"Docker","permalink":"http://nguyenvantien2009.com/tags/Docker/"},{"name":"Redis","slug":"Redis","permalink":"http://nguyenvantien2009.com/tags/Redis/"},{"name":"Install - Databases","slug":"Install-Databases","permalink":"http://nguyenvantien2009.com/tags/Install-Databases/"}],"author":"Tiển Nguyễn"},{"title":"Admin Site Components","slug":"2021/admin-ui-components","date":"2019-12-01T17:00:00.000Z","updated":"2022-06-02T08:29:39.410Z","comments":true,"path":"2021/admin-ui-components.html","link":"","permalink":"http://nguyenvantien2009.com/2021/admin-ui-components.html","excerpt":"","text":"Components need for Admin SiteIf we need a frontend framework for admin site, we need check element support in that framework have enought elements (components) are usually in admin site. Have 6 component group: From, Data, Basic, Dialog, Notification and Navigation. The main feature of frontend frameworks is the interface of the components. They are built based on a set of three important components of the web: HTML, CSS, JS. If you choose a framwork admin you should be interested in: Full of elements to use. Easy find example in github. There are specific usage examples on the official framework website. Colors, shapes, effects are relatively good. ElementElement is web component framework. It has all the components of an admin website and write in China. Element was implemented for 3 fontend framework: ReactJS, AngularJS, VueJS. It is easy to integrate with other framework. Material UIMaterial UI is good web component framework. It is built base on ReactJS and have many example use it in github. BlueprintBlueprint is a good open source for admin site. It have a lot of component UI base on ReactJS. Especially with the data table shown in very detail. We can change the data right on that table if we are in edit mode. Onsen UIOnsen UI is web component open source in mobile. We will 2 theme for components: IoS and Android. You can deploy OnSens application by 3 ways: Cordova (Hybrid App), Progressive Web Apps (PWA), Mobile and Desktop Web by Electron or Node Webkit. Please refer https://onsen.io/v2/guide/deploy.html#deploying-your-app to get more information.","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"UI Component","slug":"UI-Component","permalink":"http://nguyenvantien2009.com/tags/UI-Component/"},{"name":"Frontend","slug":"Frontend","permalink":"http://nguyenvantien2009.com/tags/Frontend/"},{"name":"Framework","slug":"Framework","permalink":"http://nguyenvantien2009.com/tags/Framework/"}],"author":"Tien Nguyen"},{"title":"Cấu Hình NGINX Cho Laravel Và AngularJS Trên Ubuntu","slug":"2021/laravel-angular-and-nginx-in-ubuntu-16.0.4","date":"2019-10-26T17:00:00.000Z","updated":"2022-06-02T08:51:12.970Z","comments":true,"path":"2021/laravel-angular-and-nginx-in-ubuntu-16.0.4.html","link":"","permalink":"http://nguyenvantien2009.com/2021/laravel-angular-and-nginx-in-ubuntu-16.0.4.html","excerpt":"","text":"Khi tôi triển khai dự án sử dụng Laravel như là một Restful API và AngularJS như là một giao diện web người dùng tôi cần phải thiết lập cho NGINX tương đối phức tạp. Bài viết này ghi lại những bước mà tôi đã thực hiện. Trong bài viết tôi giả định bạn đã cài đặt NGINX và PHP7.2 trong máy tính. Và bạn cũng đã hiểu được các bước tạo một Virtual Host trên NGINX. Tạo Client Virtual HostTrong nginx tôi đã tạo 2 virtual host được lưu trong /etc/nginx/sites-available. Và để virtual host có thể chạy được bạn cần ln -s để nó tạo tập tin liên kết trong /etc/nginx/sites-enables 1 cái dành cho angularjs (client) và một cái danh cho Laravel (api). Dưới đây là bảng tham khảo cách cấu hình nginx cho AngularJS. (Chúng tôi sử dụng HTML đã được build trong thư mục dist từ lệnh npm run build). 123456789101112131415161718192021222324# Config for Virtual Host Client.server { listen 80; server_name domain-name.com; access_log /var/log/nginx/domain-name.com.access.log; error_log /var/log/nginx/domain-name.com.error.log; # contain HTML, JS, CSS that built from AngularJS. root /home/sites/{folder contain code}; index index.html index.htm; # default show html etag on; location / { index index.html; # Use write to `index.html`. It help URL /product will run /index.html/prouct. try_files $uri /index.html; } location /api { # API start URL with /api proxy_pass http://localhost:9000/api; # Use proxy call API. proxy_set_header Host $host; }} Tạo API Virtual HostCần cấu hình Virtual Host cho Laravel. 123456789101112131415161718192021server { listen 9000; server_name localhost; access_log /var/log/nginx/api.access.log; error_log /var/log/nginx/api.error.log; root /home/sites/{code folder laravel}/public; index index.html index.htm index.php; # add index.php to run PHP code location / { # write URL to index.php. try_files $uri $uri/ /index.php?$query_string; } # It is important so this code help we can run PHP code in server. # If not eixsts it will only show as text that not run PHP code. location ~ \\.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.2-fpm.sock; }} Kết luậnSau khi đã thiết lập hoàn thành bạn cần restart nginx để cấu hình Virtual Host của mình được tải lên. Và thử chạy 2 URL trên trình duyệt [http://domain-name.com] và [http://domain-name.com/api] để nhận về kết quả.","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Server","slug":"Server","permalink":"http://nguyenvantien2009.com/tags/Server/"},{"name":"Ubuntu","slug":"Ubuntu","permalink":"http://nguyenvantien2009.com/tags/Ubuntu/"},{"name":"Laravel","slug":"Laravel","permalink":"http://nguyenvantien2009.com/tags/Laravel/"},{"name":"Nginx","slug":"Nginx","permalink":"http://nguyenvantien2009.com/tags/Nginx/"},{"name":"AngularJS","slug":"AngularJS","permalink":"http://nguyenvantien2009.com/tags/AngularJS/"},{"name":"Configuration","slug":"Configuration","permalink":"http://nguyenvantien2009.com/tags/Configuration/"}],"author":"Tiển Nguyễn"},{"title":"Xuất PDF Từ Markdown Bởi Pandoc Bằng Sublim Text","slug":"2021/export-pdf-from-markdown-by-pandoc-with-sublimetext","date":"2019-10-22T17:00:00.000Z","updated":"2022-06-02T08:35:49.293Z","comments":true,"path":"2021/export-pdf-from-markdown-by-pandoc-with-sublimetext.html","link":"","permalink":"http://nguyenvantien2009.com/2021/export-pdf-from-markdown-by-pandoc-with-sublimetext.html","excerpt":"","text":"Markdown là một ngôn ngữ giúp bạn viết những ghi chú đơn giản với định dạng tốt. Nó hỗ trợ các định dạng đẹp cho các ngôn ngữ lập trình. Do đó nó thích hợp giúp các lập trình viên viết các ghi chú và viết bài báo trên các tạp chí lập trình trực tuyến. Trong bài viết này tôi muốn kết hợp giữ Markdown và Pandoc để sỉnh ra tập tin định dạng PDF đẹp trên trình soạn thảo Sublim Text. MarkdownTôi thấy nó rất thuận tiện để viết những ghi chú của mình một cách nhanh chóng mà không cần phải mở các loại phần mềm nặng nề và phúc tạp. Với NotePad+ hay Sublime Text là tôi có thể viết ra những ghi chú của mình để xem lại trong tương lại hoặc để đang lên trang báo (hiện có nhiều trang chuyên về lập trình đã hỗ trợ Markdown như Stack Overflow, Gitlab, Github…). Thứ mà tôi thường dùng nhất là định dạng các tiêu đề như *Markdown là tiêu đề của phần bạn đang đọc. Tiếp đến là định dạng mã nguồn, thứ không thể thiếu đối với lập trình viên. Ví dụ bên dưới là cách định dạng đoạn mã JavaScript. 1234let name = 'Nguyen Van Tien';function show(name) { console.log('My nam is ' + name);} Để có được định dạng trên đơn thuần bạn chỉ cần đặt nội dung mã trong ngôn ngữ lập trình Nội dung mã trong đây PandocMột ứng dụng giúp ta có thể chuyển đổi từ định dạng này sang định dạng khác. Pandoc chuyển đổi từ Markdown sang PDF, Ebook, HTML… Pandoc cũng là nơi để tích hợp thêm các ứng dụng chuyển đổi khác để sinh ta tập tin theo ý muốn. Nếu bạn muốn sinh ra PDF bạn cần phải có --pdf-engine được cài đặt trong máy tính của mình. Thực chất Pandoc không làm nhiệm cụ chuyển đổi này mà engine mà bạn thêm vào trên máy sẽ làm. Pandoc chỉ là một nơi giao tiếp, kết nối (inteface) gữa người dùng và engine thôi. Do nó chỉ là một giao tiếp nên nếu bạn chỉ cài đặt Pandoc đơn thuần thì không có ý nghĩa. Cần phải có thêm một bộ thư việc đi kèm để có thể làm các công việc phổ biến mà người dùng thường hay sử dụng. Do đó bạn có thể sử dụng ngay những tính năng này ngay sau khi cài đặt nhưng đừng nghĩ nó là của Pandoc nha. Một ví dụ thường thấy là dùng Pandoc để chuyển đổi từ tập tin Markdown sang PDF. 1pandoc markdow.md -o pdf.pdf --pdf-engine=xelatex Ta đang chuyển đổi từ tập tin markdow.md sang pdf.pdf bằng cách sử dụng xelatex (một engine). Đôi khi bạn không cần khai báo engine nhưng vẫn chạy được là do nó sử dụng một engine mặc định. Điều này có nghĩa là nếu không có engine nào được cài đặt trên máy thì nó sẽ báo lỗi. Sublime TextĐây là công cụ phổ biến của các bạn Lập trình viên. Nó được sử dụng nhiều vì rất nhẹ (nhẹ như phần mềm Notepad của window). Tuy nhiên, nếu bạn cần sử dụng với những tính năng chuyên nghiệp thì cần cài thêm các phần mền cộng thêm được phát triển bởi cộng đồng.","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Markdown","slug":"Markdown","permalink":"http://nguyenvantien2009.com/tags/Markdown/"},{"name":"PDF","slug":"PDF","permalink":"http://nguyenvantien2009.com/tags/PDF/"},{"name":"Pandoc","slug":"Pandoc","permalink":"http://nguyenvantien2009.com/tags/Pandoc/"},{"name":"SublimeText","slug":"SublimeText","permalink":"http://nguyenvantien2009.com/tags/SublimeText/"}],"author":"Tiển Nguyễn"},{"title":"CI/CD Gitlab Setting","slug":"2021/gitlab-ci-and-cd-setting","date":"2019-10-20T17:00:00.000Z","updated":"2022-06-02T08:36:12.383Z","comments":true,"path":"2021/gitlab-ci-and-cd-setting.html","link":"","permalink":"http://nguyenvantien2009.com/2021/gitlab-ci-and-cd-setting.html","excerpt":"","text":"Tự động hóa các qui trình trong sản xuất phần mềm là một công cụ giúp nâng cao hiệu quả công việc cho các công ty công nghệ thông tin. CI/ CD là một phần trong quá trình tự động hóa này. Nó được Gitlab hỗ trợ trong phiên bản 9.0 trở lên. Bài viết này tôi xin đề cập đến làm thế nào thiết lập CI/ CD cơ bản trong gitlab. CI/ CI là gì?CI là từ được viết tắt từ Continues Integration và được hiểu là Tích hợp liên tục. Khi bạn phát triên ứng dụng bạn cần trải qua các giai đoạn phổ biến như: Test, Build. Các giai đoạn này sẽ được làm một cách tự động mà ít cần sự can thiệp của con người. Chính vì thế chất lượng phần mềm sẽ được đảm bảo hơn khi không có cảm tính trong quá trình kiểm thử. Tuy nhiên đòi hỏi Lập trình viên cần viết các mã test (unit test, integration test…) CD được viết tắt từ Continues Delivery hay Continues Deployment. Nó được xem là một giai đoạn để triển khai mã nguồn lên sản phẩm đang cung cấp. Ta có thể hiểu nó như là một gia đoạn triển khai sản phẩm trên các mội trường dev, test, staging và production. Quá trình này sẽ diễn ra một cách tự động theo một kịch bản đã được viết bởi lập trình viên. Để kích hoạt quá trình thì cần có thêm các điều kiện như test không có lỗi… Thông qua CI/ CD, các công ty phần mềm có thể triển khai các ứng dụng của mình một cách nhanh chống và an toàn. Giảm thiểu lỗi do thiếu các bước mỗi lần triển khai. Giảm thiểu chi phí cho công việc lập đi lập lại của quá trình triển khai. CI/ CD được sử dụng tốt trong các ứng dụng dạng SaaS, Cloud… trong các quy trình phần mềm Agile. Thiết lập với .gitlab-ci.ymlKhi mã nguồn bạn được commit lên repository thì gitlab sẽ có một trigger để nhận biết cần phải làm gì tiếp theo. Nếu bạn không định nghĩa các bước nào tiếp theo thì gitlab không thể thực hiện được. Do đó cần có một thứ gì đó để cho gitlab biết mình phải làm gì. .gitlab-ci.yml là tập tin định nghĩa các bước làm ấy. Người dùng cần phải tạo nó trong thư mục gốc (root) của mã nguồn repository và commit cùng với mã nguồn. 12345678910111213141516171819202122stages:- test- build- deploytest: stage: test script: echo "Running tests"build: stage: build script: echo "Building the app"deploy_staging: stage: deploy script: - echo "Deploy to staging environment" environment: name: staging url: https://staging.codetot.com only: - master Đoạn mã trên là ví dụ đơn giản của một .gitlab-ci.yml. Tôi chia quá trình phát triển phần mềm của mình là 3 giai đoạn (thể hiện trong stage): test, build và deploy. Mỗi giai đoạn sẽ thực hiện những gì sẽ được tôi định nghĩa trong đoạn mã bên trên. Ví dụ giai đoạn test tôi chỉ đơn thuận in ra câu Running tests thì đoạn mã sẽ được thể hiện. 123test: stage: test script: echo "Running tests" Tương tự ta cần tìm hiểu thêm các giai đoạn còn lại. Và để viết được nội dung thực thi trong mỗi giai đoạn bạn cần tham khảo thêm các lệnh trong CI/ CD của gitlab https://docs.gitlab.com/ee/ci/yaml/README.html. Gitlab Runner… Tôi sử dụng Docker để tạo một service Gilab Runner vì nó đơng giản nhất cho người sử dụng. Chỉ cần bạn đã có Docker Engine đã được cài đặt và chạy đoạn mã bên dưới là mọi thứ đã xong. Nếu chưa có Docker Engine, bạn có thể vào https://docs.docker.com/install/linux/docker-ce/ubuntu/ để cài đặt. 1234docker run -d --name gitlab-runner --restart always \\ -v /srv/gitlab-runner/config:/etc/gitlab-runner \\ -v /var/run/docker.sock:/var/run/docker.sock \\ gitlab/gitlab-runner:latest Bài viết này tôi giả định bạn đã biết cơ bản về Docker nên đoạn mã trên không cần phải giải thích thêm. Bây giờ ta cần đăng ký Docker Runner kết nối đến gitlab của bạn. Hãy vào Setting -> CI/ CD -> Runner. Nhấp vào Expand để thấy thông tin cấu hình. Hãy tìm Set up a specific Runner manually. Chú ý (2.) và (3.), đây là 2 thông số để chúng ta thiết lập URL và TOKEN giúp bạn kết nối giữa Gitlab Runner và Gitlab hiện tại. Cần vào lại Docker của gitlab runner để thiết lập. 1234567891011121314151617# login docker gitlab-runnerdocker exec -u root -it gitlab-runner /bin/bash# defiend parameterexport GITLAB_URL=http://gitlab.vtsspace.com/export GITLAB_TOKEN=zJU6xbGJT7tzyY9Dqmc6# registry gitlab runner to gitlabgitlab-runner \\ register -n \\ --name "Docker Runner" \\ --executor docker \\ --docker-image docker:latest \\ --docker-volumes /var/run/docker.sock:/var/run/docker.sock \\ --url $GITLAB_URL \\ --registration-token $GITLAB_TOKEN \\ --tag-list test,build,deploy Nếu bạn vào lại Runner Setting như ở trên và thấy được hình bên dưới thì Runner của bạn đã đăng ký thành công. Kiểm tra kết quảHãy vào lại dự án trong gitlab mà bạn vừa khai báo Gitlab Runner để xem kết quả. Nhấp vào CI/ CD bên ở menu bên trái. Bạn sẽ thấy được các Pipeline đã chạy. Bạn sẽ thấy được kết quả của mỗi giai đoạn (stage) của mỗi Pipeline sau mỗi lần commit mã. Nếu bạn cần thấy được chi tiết kết quả của mỗi lần chạy thì nhấp vào mỗi Pipeline Tài liệu tham khảo Gitlab CI Reference","categories":[{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"}],"tags":[{"name":"Gitlab","slug":"Gitlab","permalink":"http://nguyenvantien2009.com/tags/Gitlab/"},{"name":"CI/CD","slug":"CI-CD","permalink":"http://nguyenvantien2009.com/tags/CI-CD/"},{"name":"Process","slug":"Process","permalink":"http://nguyenvantien2009.com/tags/Process/"},{"name":"Git","slug":"Git","permalink":"http://nguyenvantien2009.com/tags/Git/"}],"author":"Tiển Nguyễn"},{"title":"Hành Trình Tiếp Cận Học Máy","slug":"2021/hanh-trinh-tiep-can-may-hoc","date":"2019-10-10T17:00:00.000Z","updated":"2022-06-02T09:11:47.712Z","comments":true,"path":"2021/hanh-trinh-tiep-can-may-hoc.html","link":"","permalink":"http://nguyenvantien2009.com/2021/hanh-trinh-tiep-can-may-hoc.html","excerpt":"","text":"Hành trình tiếp cận máy họcHọc máy được lên ngôi trong giai đoạn hiện tại (2019-2020). Nên hầu hết các chương trình điều dựa trên những thành tựu của học máy như là một phương tiện để quảng bá thương hiệu tốt. Do đó các bạn sinh viên đang tìm chương trình giảng dạy, doanh nghiệp để đầu tư. Nhưng nếu bạn chưa có khả năng để tiếp cận được những chương trình ấy thì tài liệu này giúp bạn định hướng để bạn có thể tiếp cận tốt với học máy. Công cụCông cụ là thứ bạn cần trước tiên khi bắt đầu. Bạn sẽ có nhiều thứ công cụ phục vụ cho máy học. Song chúng tôi chỉ đề cập các công cụ tất yếu để bạn có thể tiếp cận nhanh. Trình soạn thảo (Editor) là nơi để bạn gõ mã thực thi chương trình. Bạn có thể dùng Nodepad. Nhưng thuận tiện hơn thì ta nên dùng các trình soạn thảo chuyên lập trình. Đặc biệt là dành cho máy học. Thư viện (Library, Framework) Dữ liệu (Data) Biểu đồ trực quang (Visualization) Đánh giá (Evalue) Thuật toánThuật toán thì rất nhiều. Nó phù hợp với mục đích và từng loại dữ liệu khác nhau. Nó cũng sẽ cho ra kết quả với tỉ lệ chấp nhận được cũng khác nhau. Ở cấp độ đơn giản ta cần phải nắm được các thuật toán: K-Means (3ngày) HAC (3 ngày) Soạn thảoNguồn dữ liệuNguồn kiến thứcNhân vậtTài liệu tham khảo","categories":[{"name":"Máy học","slug":"May-hoc","permalink":"http://nguyenvantien2009.com/categories/May-hoc/"}],"tags":[{"name":"Machine Learning","slug":"Machine-Learning","permalink":"http://nguyenvantien2009.com/tags/Machine-Learning/"},{"name":"Journey","slug":"Journey","permalink":"http://nguyenvantien2009.com/tags/Journey/"},{"name":"Approach","slug":"Approach","permalink":"http://nguyenvantien2009.com/tags/Approach/"}],"author":"Tien Nguyen"},{"title":"Install Yarn in Ubuntu 16.0.4","slug":"2021/install-yarn-in-ubunu-16.0.4","date":"2019-10-10T17:00:00.000Z","updated":"2022-06-02T08:50:28.921Z","comments":true,"path":"2021/install-yarn-in-ubunu-16.0.4.html","link":"","permalink":"http://nguyenvantien2009.com/2021/install-yarn-in-ubunu-16.0.4.html","excerpt":"","text":"Cài đặt Yarn trong Ubuntu 16.0.4Ngày 24 tháng 09 năm 2019 bởi Tiển Nguyễn Nếu bạn cài đặt yarn theo hướng dẫn phổ biến từ cmdtest bạn sẽ gặp lỗi khi cố gắng chạy lệnh cài đặt các mô-đun trong một dự án NodeJS. Do đó ta cần phải tải mã nguồn từ github để đảm bảo có được phiên bản yarn như ý muốn của mình. Dưới đây là các dòng lệnh để cài đặt yarn. Trước tiên ta cần xóa đi các gói hiện tại đã được cài đặt trên máy tính. 12sudo apt remove cmdtestsudo apt remove yarn Thiết lập đường dẫn repository để tải bản yarn bằng khối lệnh dưới. 12curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list Sau khi thêm đường dẫn vào trong repository trong Ubuntu. Ta cần tải về máy tính của mình sau đó cài đặt. 12sudo apt-get updatesudo apt-get install yarn Bây giờ bạn đã hoàn toàn có thể sử dụng yarn trên máy tính của mình. Hãy gõ lệnh yarn install.","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Server","slug":"Server","permalink":"http://nguyenvantien2009.com/tags/Server/"},{"name":"Ubuntu","slug":"Ubuntu","permalink":"http://nguyenvantien2009.com/tags/Ubuntu/"},{"name":"NodeJS","slug":"NodeJS","permalink":"http://nguyenvantien2009.com/tags/NodeJS/"},{"name":"Install","slug":"Install","permalink":"http://nguyenvantien2009.com/tags/Install/"},{"name":"Yarn","slug":"Yarn","permalink":"http://nguyenvantien2009.com/tags/Yarn/"}],"author":"Tien Nguyen"},{"title":"ĐồNg Nhất Thế Giới Số Và Thế Giới Thực","slug":"2021/mau-bao-cao-khoa-hoc","date":"2019-09-28T17:00:00.000Z","updated":"2022-06-02T08:51:30.781Z","comments":true,"path":"2021/mau-bao-cao-khoa-hoc.html","link":"","permalink":"http://nguyenvantien2009.com/2021/mau-bao-cao-khoa-hoc.html","excerpt":"","text":"Giới thiệu (Introduction)Thành quả từ thế giới số được thể hiện hàng ngày trong cuộc sống. Nhưng nếu sự sáng tạo đó không đi theo qui luật vận hành của thế giới thực sẽ là một thảm họa. Chính vì thế Thế giới số phải nên là một bản sao của thế giới thực. Và tuân theo những qui tắc tất yếu của thế giới thật. Tuy nhiên, không nên lấy đi điểm mạnh sáng tạo của nó. Chúng ta cần xác định những gì cần thiết phải phải có trong nó thôi. Hãy để sự sáng tạo không giới hạn của nó cải tạo thế giới. Phần giới thiệu cần phải thể hiện được lý do nghiên cứu, tầm quan trọng của nghiên cứu, cấu trúc của nghiên cứu, giải quyết câu hỏi nào? Lịch sử nghiên cứu trước đây (Literature review)Liệt kê sơ lược các bài báo trước đây cùng với tác giả của các bài báo đó. Đưa ra những nhược điểm hoặc phản bát kết quả nghiên cứu của họ. Nhằm làm rõ hơn đóng góp của tác giải trong bài nghiên cứu này. Phương pháp và Dữ liệu (Methodologies and Data)Bài báo cáo cho người đọc biết tác giả đã dùng phương pháp nghiên cứu nào? Mỗi đề tài có những phương pháp nghiên cứu thích hợp. Bạn không thể dùng phương pháp định lượng để nghiên cứu về văn học. Những nguồn dữ liệu sử dụng trong quá trình nghiên cứu. Nguồn dữ liệu do tác giả tự thu thập hoặc thông qua một tổ chức nào đó. Song tác giả cần cho thấy được nguồn dữ liệu của mình đáng tin và bao trùm nghiên cứu của mình. Nếu cần thiết tác giả có thể đưa ra các bằng chứng về nguồn gốc dữ liệu. Công thức toán học. Eq. $$E = m c^2$$ Kết quả và Thảo luận (Results and Discussion)Kết quả sau quá trình nghiên cứu. Nó có đóng góp được gì so với các nghiên cứu trước đây không? Hoặc chỉ là bỗ sung chi tiết thêm cho các nghiên cứu trước. Đặc biệt, tác giả cần xoái sâu vào câu hỏi mà chính mình đã trình bày ở phần giới thiệu. Nếu kết quả đã trả lời thỏa đáng câu hỏi thì nghiên cứu được xem là thành công. Kết luận (Conclusion)Tổng hợp được kết quả nghiên cứu và nêu ra ý nghĩa khoa học của nghiên cứu[^1]. Lời cảm ơn (Acknowledgements)Cảm ơn nhà tài trợ, Tổ chức hỗ trợ và các đồng nghiệp. Tài liệu tham khảo (References)[^1]: author: nobody, ID: 12345.","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Research","slug":"Research","permalink":"http://nguyenvantien2009.com/tags/Research/"},{"name":"Report","slug":"Report","permalink":"http://nguyenvantien2009.com/tags/Report/"}],"author":"Nguyễn Văn Tiển"},{"title":"Software Design Document","slug":"2021/software-design-document","date":"2019-09-28T17:00:00.000Z","updated":"2022-06-02T09:02:43.403Z","comments":true,"path":"2021/software-design-document.html","link":"","permalink":"http://nguyenvantien2009.com/2021/software-design-document.html","excerpt":"","text":"AbstractBuilding software is like building a house. We need to have a good design to make the construction process safe and fast. Software is a completely virtualized system. Therefore, it is necessary to describe the design details in order to see the application exceptions to avoid break rebuilding because the architecture does not meet the new requirements. In the article you will see the types of documents needed during the software development process. They are both a means for team members to understand each other in the communication process but also a document to help remember how the system works for the operation and maintenance stages of the system. The design document divided 3 groups: general software document, design document system and development document. These groups also respond to members whose roles vary from members who do not understand the system to customers, managers, investors, or software developers… OverviewIntroduction SystemDevelopment DocmentOverview SystemArchitech SystemData SystemFor me, this document is the most important in documents. It contain object data relationship and entity relationship in database. This document allways present as image with diagrams. Viewers easy capture contain at a glance. Data Document specify 2 types: database document and data object document. With database document we have ER Diagram. We will see how many tables the application has and how they relate to each other. In fact, the tables in the database are a mapping of an entity in ERD. Therefore, users can easily predict their relationship when referring to entities in real life. Two entities with a number of relationships can be 0, 1 or more (n). This will lead to 5 cases for the links through that system. Entity A can be related to entity B by the relation 0 - 1, 0 - n, 1 - 1, 1 - n, n - n. With data object document we have ER Model. Entities will cross system through model designs in object orientation. Usually entities cross each other through inheritance, composites or abstractions and interfaces. With these types of systems we see closer to the real world than ERD. The ER Model diagram is often more complex than ERD because it has more to show the transition between objects in different stages. ComponentUser IntefaceSoftware Requirement SpecificationProduct DocumentArchitech & DesignCode StandarTestcaseUser GuideDeploymentUML DiagramsUsecase DiagramClass DiagramSequence DiagramActivity DiagramState DiagramObject DiagramDeployement DiagramTiming Digram","categories":[{"name":"Thiết kế","slug":"Thiet-ke","permalink":"http://nguyenvantien2009.com/categories/Thiet-ke/"}],"tags":[{"name":"Document","slug":"Document","permalink":"http://nguyenvantien2009.com/tags/Document/"},{"name":"Software Design","slug":"Software-Design","permalink":"http://nguyenvantien2009.com/tags/Software-Design/"}],"author":"Tien Nguyen"},{"title":"Tạo Dự Án Với Spring Boot","slug":"2021/create-sample-project-with-spring-boot","date":"2019-08-19T17:00:00.000Z","updated":"2022-06-02T08:34:32.603Z","comments":true,"path":"2021/create-sample-project-with-spring-boot.html","link":"","permalink":"http://nguyenvantien2009.com/2021/create-sample-project-with-spring-boot.html","excerpt":"","text":"Trong bài này chúng tôi hỗ trợ bạn tạo một dự án Spring Boot đơn giản với IDE InteliJ đơn giản nhất dựa trên Maven. Bắt đầu dự án đơn giản với Spring Boot là một web service dạng Restful API. Bài viết bạn có thể xem từng bước tạo một dự án và được giải thích các bước một cách chi tiết. Cuối bài bạn có thể tải mã nguồn từ github nếu bạn cần mã nguồn đầy đủ. 1. Công cụĐây là những công cụ bạn cần cài đặt trong máy tính cá nhân của mình nếu máy tính chưa có. InteliJ (IDE). InteliJ có 2 phiên bản trả phí và phiên bản cộng đồng nên bạn cần sử dụng phiên bản cộng đồng. Chỉ có phiên bản trả phí mới hỗ trợ các bước tạo dự án Spring Boot tự động. Maven (Repository) 2. Tạo dự án Maven trong InteliJ Trong InteliJ. File -> New -> Project. Hiện hộp thoại New Project. Chọn Maven bên trái và Chọn 1.8 trong Project JDK bên phải. Định nghĩa GroupId, ArtifacId, Version. Với GroupId định nhóm dự án. Nó thường tên giống như một package lớn. ArtifacId là tên của dự án đang thực hiện. Version là phiên bản của dự án. Bây giờ chúng ta đã có dự án từ Maven mà chưa đá động gì đến Spring Boot. 3. Sử dụng Spring BootĐể sử dụng Spring Boot trong dự án được tạo từ Maven. Chúng ta cần vào pom.xml để thêm dependency của Spring Boot. Thêm parent trong pom.xml gói Spring Boot Starter. 12345<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.7.RELEASE</version></parent> Thêm dependency các gói sản phẩm từ Spring Boot. Cụ thể chúng ta có thể thêm Spring Boot Web để có thể chạy dự án trên web. 123456<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency></dependencies> Khi Spring Boot Starter Web được thêm vào pom.xml đồng nghĩa với việc các gói lên quan đến nó sẽ được thêm vào dự án. Để thấy các gói liên quan ta vào Maven để xem thêm. Dưới đây là những gói sản phẩm đi cùng Spring Boot Starter Web. Gói sản phẩm phục vụ cho chạy dự án trên nền tảng web. Spring Web (spring-web) Spring Web MVC (spring-webmvc) Gói sản phẩm thuộc Spring Boot Spring Boot Starter (spring-boot-starter) Spring Core Spring Boot: Đây được xem là tinh hoa của Spring Boot vì nó tích hợp gần như những gói sản phẩm cần thiết từ Spring Framework. Sản phẩm như: Spring Core, Spring Context, Spring Test, Spring Web, Spring Web MVC, Spring Security Web, Hibernate Core, Tomcat, Log4J… Có thể tham khảo thêm từ Spring Boot Dependency. Spring Boot Auto Configuration Spring Boot Starter Logging Spring Boot Starter JSON (spring-boot-starter-json): Sử dụng trong các Restful Service. Spring Boot Starter Tomcat (spring-boot-starter-tomcat): Để chạy web Spring Boot Web đã sử dụng tomcat là web server cho mình. Gói sản phẩm thuộc Hibernate Hibernate Validator: Gần như ta không sử dụng nhiều từ gói sản phẩm này ngoại từ jackson. Bạn có thể tham khảo thêm từ Dependency Hibernate Validator. Khi thêm dependecy trên là ta đã có các sản phẩm tích hợp vào dự án. Bây giờ chỉ cần sử dụng. 4. Tạo Restful Service đơn giảnĐể chạy được Spring Boot ta cần phải có main trong một class nào đó. Nó giống như ta tạo một dự án Java Console vậy. Ở đây chúng ta tạo class main để có thể chạy Spring Boot như một web trong src/main/java/Main.class. 123456public class Main { public static void main(String[] args) { // Need Start Spring Boot in here }} Chỉ thế thì chưa thể chạy Spring Boot mà chỉ có thể chạy được dự án Java Console. Do đó ta cần thêm Annotation giúp cấu hình Spring Boot. 12345// Setting Spring Boot@EnableAutoConfiguration// Run Spring Boot ApplicationSpringApplication.run(Main.class, args); Bây giờ sẽ là Class hoàn chỉnh của Main. 123456789101112131415161718import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@EnableAutoConfigurationpublic class Main { @RequestMapping("/") String home() { return "Hello world"; } public static void main(String[] args) { SpringApplication.run(Main.class, args); }} Chạy dự án từ IDE chúng ta sẽ thấy được kết quả. Từ trình duyệt truy cập http://localhost:8080 ta sẽ thấy được dòng Hello word cho hàm home trả về trong RestController. 5. Liên kết tham khảo Mã nguồn từ github cho Bắt đầu dự án đơn giản với Spring Boot","categories":[],"tags":[{"name":"Starter","slug":"Starter","permalink":"http://nguyenvantien2009.com/tags/Starter/"},{"name":"Spring Boot","slug":"Spring-Boot","permalink":"http://nguyenvantien2009.com/tags/Spring-Boot/"}],"author":"Tiển Nguyễn"},{"title":"Phân Loại Các Thuật Toán Máy Học","slug":"2021/phan-loai-cac-thuat-toan-nay-hoc","date":"2019-08-17T17:00:00.000Z","updated":"2022-06-02T08:52:45.424Z","comments":true,"path":"2021/phan-loai-cac-thuat-toan-nay-hoc.html","link":"","permalink":"http://nguyenvantien2009.com/2021/phan-loai-cac-thuat-toan-nay-hoc.html","excerpt":"","text":"Phân loại học máyCó nhiều cách phân loại theo hướng nhìn khác nhau. Song có 2 cách được thừa nhận rộng rãi là phân loại theo cách học và phân loại theo kiểu dữ liệu. Phân loại dữ liệuCăn cứ vào đặc tính của dữ liệu mà ta chia làm 4 loại để thuận tiện cho việc giao tiếp. Học máy được chia dựa trên dữ liệu đầu vào và dữ liệu đầu ra. Hãy hình dung như một hàm trong lập trình đưa dữ liệu vào sau đó thực hiện thuật toán và xuất dữ liệu ra như ta mong muốn. Nhưng đối với học máy thì những bước thực thi (nội dụng hàm) trở thành một thứ mà ta cần tìm (xem như là một hộp đen). Đối với dữ liệu ta có 2 loại: có dán nhãn và chưa được dán nhãn. Đối với dữ hiệu có dán nhãn được xem là dữ liệu đã biết kết quả nhưng ta vẫn dùng nó để hệ thống có thể học nhằm nhận biết các dữ liệu chưa được dán nhãn trong ứng dụng. Đối với dữ liệu chưa được dán nhãn đồng nghĩa với dữ liệu ta không biết đúng hoặc sai như thế nào. Nhiệm vụ của chương trình học là phải tìm ra qui luật để xác định, phân loại dữ liệu. 1. Học có giám sát (Supervised Learning)2. Học không giám sát (Un-Supervised Learning)","categories":[{"name":"Máy học","slug":"May-hoc","permalink":"http://nguyenvantien2009.com/categories/May-hoc/"}],"tags":[{"name":"Machine Learning","slug":"Machine-Learning","permalink":"http://nguyenvantien2009.com/tags/Machine-Learning/"},{"name":"Approach","slug":"Approach","permalink":"http://nguyenvantien2009.com/tags/Approach/"},{"name":"Algorithm","slug":"Algorithm","permalink":"http://nguyenvantien2009.com/tags/Algorithm/"}],"author":"Tien Nguyen"},{"title":"Cài đặT Odod SaaS Bằng Docker","slug":"2021/install-odoo-by-docker","date":"2019-06-09T17:00:00.000Z","updated":"2022-06-02T08:48:23.487Z","comments":true,"path":"2021/install-odoo-by-docker.html","link":"","permalink":"http://nguyenvantien2009.com/2021/install-odoo-by-docker.html","excerpt":"","text":"SaaS Odoo được cung cấp bởi một công ty khác. Nó không thuộc Odoo. Do đó sẽ có những vấn đề không tương thích khi cố gắn cài đặt SaaS Odoo. Vì vậy Docker là một chọn lựa tuyệt vời để triển khai Odoo trên các hệ thống máy chủ nhanh và ổn định. Cài đặt1. Docker EngineTrong bài này chúng ta không đề cập cách cài đặt Docker Engine vì nó quá phổ biến trên các bài báo khác. Dễ dang tìm và cài đặt. 2. Cài đặt Network Docker1docker network create odoo-saas 3. Cài đặt Postgres DockerChúng ta sử dụng Postgres 9.6 cho Odoo 11.0. Tùy version Odoo ta cần cài đặt version phù hợp. 1234567docker run \\-d \\-e POSTGRES_USER=odoo \\-e POSTGRES_PASSWORD=odoo \\--network=odoo-saas \\--name db-saas \\postgres:9.6 4. Cài đặt Odoo Docker12345678docker run \\-d \\--name odoo \\--network=odoo-saas \\-e ODOO_MASTER_PASS=admin \\-e DB_PORT_5432_TCP_ADDR=db-saas \\-v /mnt/addons/extras:/mnt/addons/extras \\-t itprojectsllc/install-odoo:11.0 Thay đổi cách cấu hình mặt định của Odoo để có thể nhận sub-domain làm tên databse. 1234docker exec \\ -u root \\ -t odoo \\sed -i 's/dbfilter.*/dbfilter = ^%d$/' /mnt/config/odoo-server.conf Restart Odoo Docker 1docker restart odoo Ta cần cài đặt nginx làm proxy để có thể chạy được cổng 80 (cổng mặc định của chạy website) thay vì phải chạy web với port mặt định từ Odoo. 123456docker run \\-d \\-p 80:80 \\--name saas-nginx \\--network=odoo-saas \\-t itprojectsllc/docker-odoo-nginx 5. Cài đặt SaaSBây giờ ta mới tiến hành cài SaaS bằng các dòng lệnh trong odoo-install-saas.sh. Tập tin này chứa mã để tiến hành tương tác với hệ thống Odoo. 12345678910111213INIT_SAAS_TOOLS_VALUE=' \\--portal-create \\--server-create \\--plan-create \\--odoo-script=/mnt/odoo-source/odoo-bin \\--odoo-config=/mnt/config/odoo-server.conf \\--portal-db-name=portal \\--server-db-name=server-1 \\--server-hosts-template={dbname}.{base_saas_domain_1} \\--plan-template-db-name=template-1 \\--plan-clients=demo-%i \\' && docker exec -u root -t odoo /bin/bash \\-c "export INIT_SAAS_TOOLS='$INIT_SAAS_TOOLS_VALUE'; bash /install-odoo-saas.sh" Nếu ta cài trên máy tính cá nhân (local) thì dến đây xem như hoàn thành. Nhưng nếu ta đang cài trên host thì cần phải chạy thêm đoạn mã sau để tiến hành thay đổi cấu hình của Odoo cho phù hợp. 123456789sudo echo && INIT_SAAS_TOOLS_VALUE=' \\--print-local-hosts \\--odoo-script=/mnt/odoo-source/odoo-bin \\--odoo-config=/mnt/config/odoo-server.conf \\--suffix=sems.vn \\--portal-db-name=portal.{suffix} \\--server-db-name=server-1.{suffix} \\--plan-template-db-name=template-1.{suffix} \\' && sudo bash -c "docker exec -u odoo -t odoo bash -c \\"python /mnt/addons/it-projects-llc/odoo-saas-tools/saas.py ${INIT_SAAS_TOOLS_VALUE}\\" >> /etc/hosts" Đến đây ta có thể hoàn toàn chạy được http://portal.sems.vn với domain sems.vn đã được thiết lập trong tùy chọn lúc thực thi câu lệnh ở trên. Mọi cài dặt đã hoàn thành. Một thứ mà bạn có thể thỉnh thoảng thấy trong quá trình cài đặt là Odoo báo lỗi về mã hóa mật khẩu khi tạo mới một Client trong Portal site. Lỗi này tôi vẫn chưa thể giải quyết được ngoài việc cố gắn thực hiện lại quá trình cài đặt. Tạo DatabaseTạo database bằng Backend với tài khoản AdminVới phương thức này ta cần có tài khoản Admin để có thể đăng nhập vào portal site. Đăng nhập SaaS Portal. Đường dẫn của SaaS Portal bạn có thể cấu hình lại trong quá trình cài đặt. Vào menu trên đầu SaaS -> Plan. Chọn Plan muốn tạo. Đăng nhập database template (Login Database Template) để tạo nên một database mẫu khi ta tạo cho khách hàng. Ví dụ nếu tạo PoS cho khách hàng thì ta chỉ cần cài đặt sẳn các module của PoS. Tạo khách hàng bằng nút Create Client. Đã xong. Cuối cùng bạn cần login vào client để kiểm tra lại. Tạo database bằng Frontend với tài khoản ClientKhách hàng có thể tự đăng ký để tạo một database riêng cho mình mà không cần Admin. Để tạo theo cách này khách hàng cần phải biết được plan_id (nếu sai plan_id thì hệ thống sẽ tạo ra một database dựa trên mẫu sai nên không dùng được) và nhập thông tin đăng ký để hoàn thành. Không cần Login. Nhập đường dẫn {portal-domain}/page/start?plan_id=1 (cần xác định đúng plan_id). Gõ tên database muốn tạo. Tên này tương ứng với tên khách hàng và sẽ là sub-domain khi khách hàng sử dụng. Nhập nút tạo. Nhưng hệ thống yêu cầu ta đăng nhập. Không có tài khoản do đó ta cần đăng ký. Và nhập đầy đủ thông tin để đăng ký. Sau khi đăng ký xong. Một databse mới được tạo và hệ thống sẽ tự động nhảy đến website của khách hàng. Mở lên vào sử dụng thôi (Mặt định tài khoản là admin/ admin) Những phần của Odoo SaaSBình thường Odoo chỉ có 1 database của nó. Nhưng nếu triển khai SaaS thì chúng ta cần đến 3 database để quản lý hệ thống. Portal là một bộ phận chính của hệ thống để ta có thể thao tác đến các server, client, template và plant. Server là kỹ thuật quản lý database. Mục tiêu là quản lý các database của khách hàng (client). Tại đây ta có thể tạo, sửa và xóa database. Đặt biệc là các server có thể cài đặt trên nhiều máy chủ vật lý hay VPS (Virtual Private Server). Client là database của khách hàng. Mỗi khách hàng sẽ có một database riêng và Server sẽ là bộ phận quản lý nó. Tài liệu tham khảo Mã nguồn Odoo SaaS từ Github Cấu trúc tính năng của Odoo SaaS Bài hướng dẫn cài đặt Odoo SaaS bằng Docker Tài liệu tham khảo về Odds Reference","categories":[{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"}],"tags":[{"name":"Docker","slug":"Docker","permalink":"http://nguyenvantien2009.com/tags/Docker/"},{"name":"Odoo","slug":"Odoo","permalink":"http://nguyenvantien2009.com/tags/Odoo/"},{"name":"SaaS","slug":"SaaS","permalink":"http://nguyenvantien2009.com/tags/SaaS/"},{"name":"ERP","slug":"ERP","permalink":"http://nguyenvantien2009.com/tags/ERP/"}],"author":"Tiển Nguyễn"}],"categories":[{"name":"Máy học","slug":"May-hoc","permalink":"http://nguyenvantien2009.com/categories/May-hoc/"},{"name":"Công cụ","slug":"Cong-cu","permalink":"http://nguyenvantien2009.com/categories/Cong-cu/"},{"name":"Sử dụng","slug":"Su-dung","permalink":"http://nguyenvantien2009.com/categories/Su-dung/"},{"name":"Thủ thuật","slug":"Thu-thuat","permalink":"http://nguyenvantien2009.com/categories/Thu-thuat/"},{"name":"Hạ tầng","slug":"Ha-tang","permalink":"http://nguyenvantien2009.com/categories/Ha-tang/"},{"name":"Lý luận","slug":"Ly-luan","permalink":"http://nguyenvantien2009.com/categories/Ly-luan/"},{"name":"Lập trình","slug":"Lap-trinh","permalink":"http://nguyenvantien2009.com/categories/Lap-trinh/"},{"name":"Thiết kế","slug":"Thiet-ke","permalink":"http://nguyenvantien2009.com/categories/Thiet-ke/"}],"tags":[{"name":"Machine Learning","slug":"Machine-Learning","permalink":"http://nguyenvantien2009.com/tags/Machine-Learning/"},{"name":"Data Engineer","slug":"Data-Engineer","permalink":"http://nguyenvantien2009.com/tags/Data-Engineer/"},{"name":"Pandas","slug":"Pandas","permalink":"http://nguyenvantien2009.com/tags/Pandas/"},{"name":"Visualization","slug":"Visualization","permalink":"http://nguyenvantien2009.com/tags/Visualization/"},{"name":"Data Scientist","slug":"Data-Scientist","permalink":"http://nguyenvantien2009.com/tags/Data-Scientist/"},{"name":"Python Library","slug":"Python-Library","permalink":"http://nguyenvantien2009.com/tags/Python-Library/"},{"name":"mlflow","slug":"mlflow","permalink":"http://nguyenvantien2009.com/tags/mlflow/"},{"name":"mlflow-tracking","slug":"mlflow-tracking","permalink":"http://nguyenvantien2009.com/tags/mlflow-tracking/"},{"name":"mlflow-visualization","slug":"mlflow-visualization","permalink":"http://nguyenvantien2009.com/tags/mlflow-visualization/"},{"name":"seaborn-matplotlib","slug":"seaborn-matplotlib","permalink":"http://nguyenvantien2009.com/tags/seaborn-matplotlib/"},{"name":"mlops","slug":"mlops","permalink":"http://nguyenvantien2009.com/tags/mlops/"},{"name":"Vim","slug":"Vim","permalink":"http://nguyenvantien2009.com/tags/Vim/"},{"name":"Console","slug":"Console","permalink":"http://nguyenvantien2009.com/tags/Console/"},{"name":"NodeJS","slug":"NodeJS","permalink":"http://nguyenvantien2009.com/tags/NodeJS/"},{"name":"Typescript","slug":"Typescript","permalink":"http://nguyenvantien2009.com/tags/Typescript/"},{"name":"How","slug":"How","permalink":"http://nguyenvantien2009.com/tags/How/"},{"name":"Setup","slug":"Setup","permalink":"http://nguyenvantien2009.com/tags/Setup/"},{"name":"Odoo","slug":"Odoo","permalink":"http://nguyenvantien2009.com/tags/Odoo/"},{"name":"ERP","slug":"ERP","permalink":"http://nguyenvantien2009.com/tags/ERP/"},{"name":"XML-RPC","slug":"XML-RPC","permalink":"http://nguyenvantien2009.com/tags/XML-RPC/"},{"name":"Odoo API","slug":"Odoo-API","permalink":"http://nguyenvantien2009.com/tags/Odoo-API/"},{"name":"Icon","slug":"Icon","permalink":"http://nguyenvantien2009.com/tags/Icon/"},{"name":"Font Style","slug":"Font-Style","permalink":"http://nguyenvantien2009.com/tags/Font-Style/"},{"name":"PoS","slug":"PoS","permalink":"http://nguyenvantien2009.com/tags/PoS/"},{"name":"Printer","slug":"Printer","permalink":"http://nguyenvantien2009.com/tags/Printer/"},{"name":"Rasberry Pi","slug":"Rasberry-Pi","permalink":"http://nguyenvantien2009.com/tags/Rasberry-Pi/"},{"name":"Wireless","slug":"Wireless","permalink":"http://nguyenvantien2009.com/tags/Wireless/"},{"name":"Wireless Raspberry Pi","slug":"Wireless-Raspberry-Pi","permalink":"http://nguyenvantien2009.com/tags/Wireless-Raspberry-Pi/"},{"name":"X-Printer","slug":"X-Printer","permalink":"http://nguyenvantien2009.com/tags/X-Printer/"},{"name":"Print Receipt","slug":"Print-Receipt","permalink":"http://nguyenvantien2009.com/tags/Print-Receipt/"},{"name":"Hardware","slug":"Hardware","permalink":"http://nguyenvantien2009.com/tags/Hardware/"},{"name":"MinIO - Storage Cloud","slug":"MinIO-Storage-Cloud","permalink":"http://nguyenvantien2009.com/tags/MinIO-Storage-Cloud/"},{"name":"Install Odoo","slug":"Install-Odoo","permalink":"http://nguyenvantien2009.com/tags/Install-Odoo/"},{"name":"Wordpress","slug":"Wordpress","permalink":"http://nguyenvantien2009.com/tags/Wordpress/"},{"name":"Password","slug":"Password","permalink":"http://nguyenvantien2009.com/tags/Password/"},{"name":"Website","slug":"Website","permalink":"http://nguyenvantien2009.com/tags/Website/"},{"name":"Docker","slug":"Docker","permalink":"http://nguyenvantien2009.com/tags/Docker/"},{"name":"NGINX","slug":"NGINX","permalink":"http://nguyenvantien2009.com/tags/NGINX/"},{"name":"NGINX Proxy","slug":"NGINX-Proxy","permalink":"http://nguyenvantien2009.com/tags/NGINX-Proxy/"},{"name":"Proxy","slug":"Proxy","permalink":"http://nguyenvantien2009.com/tags/Proxy/"},{"name":"CI/CD","slug":"CI-CD","permalink":"http://nguyenvantien2009.com/tags/CI-CD/"},{"name":"Jenkins","slug":"Jenkins","permalink":"http://nguyenvantien2009.com/tags/Jenkins/"},{"name":"Automatic","slug":"Automatic","permalink":"http://nguyenvantien2009.com/tags/Automatic/"},{"name":"Registry","slug":"Registry","permalink":"http://nguyenvantien2009.com/tags/Registry/"},{"name":"NPM","slug":"NPM","permalink":"http://nguyenvantien2009.com/tags/NPM/"},{"name":"Private Registry","slug":"Private-Registry","permalink":"http://nguyenvantien2009.com/tags/Private-Registry/"},{"name":"SSL","slug":"SSL","permalink":"http://nguyenvantien2009.com/tags/SSL/"},{"name":"SSL Certification","slug":"SSL-Certification","permalink":"http://nguyenvantien2009.com/tags/SSL-Certification/"},{"name":"Docker Registry","slug":"Docker-Registry","permalink":"http://nguyenvantien2009.com/tags/Docker-Registry/"},{"name":"Docker Repository","slug":"Docker-Repository","permalink":"http://nguyenvantien2009.com/tags/Docker-Repository/"},{"name":"Docker Image Hosting","slug":"Docker-Image-Hosting","permalink":"http://nguyenvantien2009.com/tags/Docker-Image-Hosting/"},{"name":"Microservice","slug":"Microservice","permalink":"http://nguyenvantien2009.com/tags/Microservice/"},{"name":"MoleculerJS","slug":"MoleculerJS","permalink":"http://nguyenvantien2009.com/tags/MoleculerJS/"},{"name":"Transporters","slug":"Transporters","permalink":"http://nguyenvantien2009.com/tags/Transporters/"},{"name":"Cluster Nodes","slug":"Cluster-Nodes","permalink":"http://nguyenvantien2009.com/tags/Cluster-Nodes/"},{"name":"Swagger","slug":"Swagger","permalink":"http://nguyenvantien2009.com/tags/Swagger/"},{"name":"OpenAPI","slug":"OpenAPI","permalink":"http://nguyenvantien2009.com/tags/OpenAPI/"},{"name":"Github","slug":"Github","permalink":"http://nguyenvantien2009.com/tags/Github/"},{"name":"Github Page","slug":"Github-Page","permalink":"http://nguyenvantien2009.com/tags/Github-Page/"},{"name":"Document","slug":"Document","permalink":"http://nguyenvantien2009.com/tags/Document/"},{"name":"Dockerfile","slug":"Dockerfile","permalink":"http://nguyenvantien2009.com/tags/Dockerfile/"},{"name":"Rest","slug":"Rest","permalink":"http://nguyenvantien2009.com/tags/Rest/"},{"name":"API","slug":"API","permalink":"http://nguyenvantien2009.com/tags/API/"},{"name":"Build Docker","slug":"Build-Docker","permalink":"http://nguyenvantien2009.com/tags/Build-Docker/"},{"name":"Deploy Docker","slug":"Deploy-Docker","permalink":"http://nguyenvantien2009.com/tags/Deploy-Docker/"},{"name":"Star","slug":"Star","permalink":"http://nguyenvantien2009.com/tags/Star/"},{"name":"Research","slug":"Research","permalink":"http://nguyenvantien2009.com/tags/Research/"},{"name":"Learn","slug":"Learn","permalink":"http://nguyenvantien2009.com/tags/Learn/"},{"name":"Starter","slug":"Starter","permalink":"http://nguyenvantien2009.com/tags/Starter/"},{"name":"Ionic","slug":"Ionic","permalink":"http://nguyenvantien2009.com/tags/Ionic/"},{"name":"References","slug":"References","permalink":"http://nguyenvantien2009.com/tags/References/"},{"name":"Moleculer","slug":"Moleculer","permalink":"http://nguyenvantien2009.com/tags/Moleculer/"},{"name":"Populate","slug":"Populate","permalink":"http://nguyenvantien2009.com/tags/Populate/"},{"name":"Model","slug":"Model","permalink":"http://nguyenvantien2009.com/tags/Model/"},{"name":"Developer Tools","slug":"Developer-Tools","permalink":"http://nguyenvantien2009.com/tags/Developer-Tools/"},{"name":"Management Tools","slug":"Management-Tools","permalink":"http://nguyenvantien2009.com/tags/Management-Tools/"},{"name":"Gitlab","slug":"Gitlab","permalink":"http://nguyenvantien2009.com/tags/Gitlab/"},{"name":"Gitlab Runner","slug":"Gitlab-Runner","permalink":"http://nguyenvantien2009.com/tags/Gitlab-Runner/"},{"name":"Slack","slug":"Slack","permalink":"http://nguyenvantien2009.com/tags/Slack/"},{"name":"Zoom","slug":"Zoom","permalink":"http://nguyenvantien2009.com/tags/Zoom/"},{"name":"Trello","slug":"Trello","permalink":"http://nguyenvantien2009.com/tags/Trello/"},{"name":"Git","slug":"Git","permalink":"http://nguyenvantien2009.com/tags/Git/"},{"name":"Notification","slug":"Notification","permalink":"http://nguyenvantien2009.com/tags/Notification/"},{"name":"Slack Webhook","slug":"Slack-Webhook","permalink":"http://nguyenvantien2009.com/tags/Slack-Webhook/"},{"name":"Device size","slug":"Device-size","permalink":"http://nguyenvantien2009.com/tags/Device-size/"},{"name":"CSS Screen","slug":"CSS-Screen","permalink":"http://nguyenvantien2009.com/tags/CSS-Screen/"},{"name":"Bootstrap Screen","slug":"Bootstrap-Screen","permalink":"http://nguyenvantien2009.com/tags/Bootstrap-Screen/"},{"name":"PDF","slug":"PDF","permalink":"http://nguyenvantien2009.com/tags/PDF/"},{"name":"Signature","slug":"Signature","permalink":"http://nguyenvantien2009.com/tags/Signature/"},{"name":"document","slug":"document","permalink":"http://nguyenvantien2009.com/tags/document/"},{"name":"document rest api","slug":"document-rest-api","permalink":"http://nguyenvantien2009.com/tags/document-rest-api/"},{"name":"swagger","slug":"swagger","permalink":"http://nguyenvantien2009.com/tags/swagger/"},{"name":"swagger edit","slug":"swagger-edit","permalink":"http://nguyenvantien2009.com/tags/swagger-edit/"},{"name":"Pankod","slug":"Pankod","permalink":"http://nguyenvantien2009.com/tags/Pankod/"},{"name":"Framework NodeJS","slug":"Framework-NodeJS","permalink":"http://nguyenvantien2009.com/tags/Framework-NodeJS/"},{"name":"Hexo","slug":"Hexo","permalink":"http://nguyenvantien2009.com/tags/Hexo/"},{"name":"Hexo Command","slug":"Hexo-Command","permalink":"http://nguyenvantien2009.com/tags/Hexo-Command/"},{"name":"Server","slug":"Server","permalink":"http://nguyenvantien2009.com/tags/Server/"},{"name":"Linux","slug":"Linux","permalink":"http://nguyenvantien2009.com/tags/Linux/"},{"name":"Window","slug":"Window","permalink":"http://nguyenvantien2009.com/tags/Window/"},{"name":"Kill","slug":"Kill","permalink":"http://nguyenvantien2009.com/tags/Kill/"},{"name":"Kill Process","slug":"Kill-Process","permalink":"http://nguyenvantien2009.com/tags/Kill-Process/"},{"name":"Firewall","slug":"Firewall","permalink":"http://nguyenvantien2009.com/tags/Firewall/"},{"name":"Allow/Disable Accesss Port","slug":"Allow-Disable-Accesss-Port","permalink":"http://nguyenvantien2009.com/tags/Allow-Disable-Accesss-Port/"},{"name":"Blog","slug":"Blog","permalink":"http://nguyenvantien2009.com/tags/Blog/"},{"name":"Wordpress Theme","slug":"Wordpress-Theme","permalink":"http://nguyenvantien2009.com/tags/Wordpress-Theme/"},{"name":"PoS Box","slug":"PoS-Box","permalink":"http://nguyenvantien2009.com/tags/PoS-Box/"},{"name":"Raspberry","slug":"Raspberry","permalink":"http://nguyenvantien2009.com/tags/Raspberry/"},{"name":"Process","slug":"Process","permalink":"http://nguyenvantien2009.com/tags/Process/"},{"name":"HapiJS","slug":"HapiJS","permalink":"http://nguyenvantien2009.com/tags/HapiJS/"},{"name":"Restful","slug":"Restful","permalink":"http://nguyenvantien2009.com/tags/Restful/"},{"name":"Deployment","slug":"Deployment","permalink":"http://nguyenvantien2009.com/tags/Deployment/"},{"name":"Load Balancing","slug":"Load-Balancing","permalink":"http://nguyenvantien2009.com/tags/Load-Balancing/"},{"name":"PM2","slug":"PM2","permalink":"http://nguyenvantien2009.com/tags/PM2/"},{"name":"MongoDB","slug":"MongoDB","permalink":"http://nguyenvantien2009.com/tags/MongoDB/"},{"name":"Install","slug":"Install","permalink":"http://nguyenvantien2009.com/tags/Install/"},{"name":"Databases","slug":"Databases","permalink":"http://nguyenvantien2009.com/tags/Databases/"},{"name":"Backup Restore","slug":"Backup-Restore","permalink":"http://nguyenvantien2009.com/tags/Backup-Restore/"},{"name":"PHP","slug":"PHP","permalink":"http://nguyenvantien2009.com/tags/PHP/"},{"name":"Laravel","slug":"Laravel","permalink":"http://nguyenvantien2009.com/tags/Laravel/"},{"name":"CORS","slug":"CORS","permalink":"http://nguyenvantien2009.com/tags/CORS/"},{"name":"Ubuntu","slug":"Ubuntu","permalink":"http://nguyenvantien2009.com/tags/Ubuntu/"},{"name":"Crontab","slug":"Crontab","permalink":"http://nguyenvantien2009.com/tags/Crontab/"},{"name":"Syspass","slug":"Syspass","permalink":"http://nguyenvantien2009.com/tags/Syspass/"},{"name":"Redis","slug":"Redis","permalink":"http://nguyenvantien2009.com/tags/Redis/"},{"name":"Install - Databases","slug":"Install-Databases","permalink":"http://nguyenvantien2009.com/tags/Install-Databases/"},{"name":"UI Component","slug":"UI-Component","permalink":"http://nguyenvantien2009.com/tags/UI-Component/"},{"name":"Frontend","slug":"Frontend","permalink":"http://nguyenvantien2009.com/tags/Frontend/"},{"name":"Framework","slug":"Framework","permalink":"http://nguyenvantien2009.com/tags/Framework/"},{"name":"Nginx","slug":"Nginx","permalink":"http://nguyenvantien2009.com/tags/Nginx/"},{"name":"AngularJS","slug":"AngularJS","permalink":"http://nguyenvantien2009.com/tags/AngularJS/"},{"name":"Configuration","slug":"Configuration","permalink":"http://nguyenvantien2009.com/tags/Configuration/"},{"name":"Markdown","slug":"Markdown","permalink":"http://nguyenvantien2009.com/tags/Markdown/"},{"name":"Pandoc","slug":"Pandoc","permalink":"http://nguyenvantien2009.com/tags/Pandoc/"},{"name":"SublimeText","slug":"SublimeText","permalink":"http://nguyenvantien2009.com/tags/SublimeText/"},{"name":"Journey","slug":"Journey","permalink":"http://nguyenvantien2009.com/tags/Journey/"},{"name":"Approach","slug":"Approach","permalink":"http://nguyenvantien2009.com/tags/Approach/"},{"name":"Yarn","slug":"Yarn","permalink":"http://nguyenvantien2009.com/tags/Yarn/"},{"name":"Report","slug":"Report","permalink":"http://nguyenvantien2009.com/tags/Report/"},{"name":"Software Design","slug":"Software-Design","permalink":"http://nguyenvantien2009.com/tags/Software-Design/"},{"name":"Spring Boot","slug":"Spring-Boot","permalink":"http://nguyenvantien2009.com/tags/Spring-Boot/"},{"name":"Algorithm","slug":"Algorithm","permalink":"http://nguyenvantien2009.com/tags/Algorithm/"},{"name":"SaaS","slug":"SaaS","permalink":"http://nguyenvantien2009.com/tags/SaaS/"}]}