diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d431612..b72ce5d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ -Contributions are greatly appreciated and here are different ways +Contributions are greatly appreciated and here are different ways: 1. :star: [Star it][linkProjectRepo]! 1. :mega: Share with your friends! diff --git a/README.md b/README.md index e9b7846..dd67732 100644 --- a/README.md +++ b/README.md @@ -98,13 +98,13 @@ Test your code and pipelines locally before your CI/CD tool runs it. Feel confid Animated demo -_The demo was generated with VHS using the 3 Musketeers ([source](demo))_ +_The demo was generated with VHS using the 3 Musketeers ([source](demo))._ ## Getting started -Let's print out `Hello, World!` in the console using the 3 Musketeers. The command `make echo` will be calling Docker to run the command `echo 'Hello, World!'` inside a container. +Let's print out `Hello, World!` in the terminal using the 3 Musketeers. The command `make echo` will be calling Docker to run the command `echo 'Hello, World!'` inside a container. ```mermaid @@ -123,7 +123,7 @@ graph LR ### Hello, World! -Create the following two files +Create the following two files: ```yaml # docker-compose.yml @@ -139,10 +139,10 @@ echo: docker compose run --rm alpine echo 'Hello, World!' ``` -Then simply echo "Hello, World!" with the following command: +Then simply run: ```bash -$ make echo +make echo ```
@@ -165,35 +165,35 @@ This repository is the [3 Musketeers website][link3Musketeers] website built wit ```bash # create a .env file -$ make envfile ENVFILE=env.example +make envfile ENVFILE=env.example # install dependencies -$ make deps +make deps # start vitepress server for local development -$ make dev +make dev # wait till the message 'vite v2.5.3 dev server running at' appears # access the website in your browser at http://localhost:8080/ # \ to stop # build static site -$ make build +make build # serve static site for local development -$ make serveDev +make serveDev # access the website in your browser at http://localhost:8080/ # \ to stop # serve static website (headless) -$ make serve +make serve # test static website -$ make test +make test # prune -$ make prune +make prune # contributing? make sure the following command runs successfully -$ make all +make all ``` ### Deployment @@ -206,13 +206,13 @@ This section creates a new empty Netlify site. Ensure the `.env` file contains t ```bash # All the following commands will be run inside a container -$ make shell +make shell # Disable telemetry (optional) -$ yarn run netlify --telemetry-disable +yarn run netlify --telemetry-disable # Create new Netlify blank site -$ yarn run netlify sites:create --disable-linking +yarn run netlify sites:create --disable-linking # Answer the questions regarding the team and site name # Site name can be something like 3musketeers-preview-{random 5 digit numbers} Site Created @@ -222,12 +222,12 @@ URL: https://site-name.netlify.app Site ID: site-id # You can always get back that information -$ yarn run netlify sites:list +yarn run netlify sites:list # Copy the ID to .env # Exit the container -$ exit +exit ``` #### Deploy @@ -236,13 +236,13 @@ This section deploys the website to an existing netlify site. Ensure the `.env` ```bash # Build the website -$ make build +make build # Deploy to netlify -$ make deploy +make deploy # Test the website -$ curl https://site-name.netlify.app +curl https://site-name.netlify.app # Clean up directory -$ make prune +make prune ``` #### Delete @@ -251,13 +251,13 @@ This section deletes a netlify site. Ensure the `.env` file contains the right s ```bash # All the following commands will be run inside a container -$ make shell +make shell # Disable telemetry (optional) -$ yarn run netlify --telemetry-disable +yarn run netlify --telemetry-disable # Delete the site (optional) -$ yarn run netlify sites:delete +yarn run netlify sites:delete # Exit the container -$ exit +exit ``` ### CI/CD diff --git a/docs/guide/contributing.md b/docs/guide/contributing.md index b08c024..4aca59c 100644 --- a/docs/guide/contributing.md +++ b/docs/guide/contributing.md @@ -2,7 +2,7 @@ -Contributions are greatly appreciated and here are different ways +Contributions are greatly appreciated and here are different ways: 1. :star: [Star it][linkProjectRepo]! 1. :mega: Share with your friends! diff --git a/docs/guide/docker.md b/docs/guide/docker.md index 3892e05..ad5b329 100644 --- a/docs/guide/docker.md +++ b/docs/guide/docker.md @@ -16,6 +16,7 @@ Docker images are like any other software. You should do your own research befor * [jwilder/dockerize][linkDockerHubDockerize]: There is often a need to wait for a service to start before interacting with it. For instance, waiting for a database container to be ready before running a migration. The image `jwilder/dockerize` can be used to help with this scenario. ```makefile + # Makefile dbStart: docker compose up -d db docker compose run --rm dockerize -wait tcp://db:3306 -timeout 60s @@ -26,7 +27,7 @@ Docker images are like any other software. You should do your own research befor ## Accessing host's localhost from a container -On Windows/Mac, accessing the host localhost is to use the url like `host.docker.internal`. This is handy because if you have an application running on `localhost:3000` locally (through container or not), then you can access it `$ curl host.docker.internal:3000`. +On Windows/Mac, accessing the host localhost is to use the url like `host.docker.internal`. This is handy because if you have an application running on `localhost:3000` locally (through container or not), then you can access it `curl host.docker.internal:3000`. ## Image without Make @@ -37,9 +38,9 @@ One of the examples in section [Patterns][linkPatterns] is to call Make from Com Often image publishers offer different versions of the application/product. For instance [golang][linkGolang] has an image based on `alpine` which does not have `make`. It also has an image based on `stretch` which does. ```bash -$ docker run --rm golang:alpine make +docker run --rm golang:alpine make # "exec: \"make\": executable file not found -$ docker run --rm golang:stretch make +docker run --rm golang:stretch make # make: *** No targets specified and no makefile found ``` @@ -49,17 +50,16 @@ If you only want to call `make` with common shell commands, or want to use `git` ### Install Make on the fly -Whenever a command runs another command it installs `make` and then executes `$ make _target`. Depending on how many times a command is run, this may be inefficient as it needs to download `make` every time. +Whenever a command runs another command it installs `make` and then executes `make _target`. Depending on how many times a command is run, this may be inefficient as it needs to download `make` every time. -```bash +```makefile +# Makefile MAKEFILE_DIR := $(dir $(abspath $(firstword $(MAKEFILE_LIST)))) - hello: docker run --rm \ -v $(MAKEFILE_DIR)Makefile:/opt/app/Makefile \ -w /opt/app \ alpine sh -c "apk add --update make && make _hello" - _hello: echo "Hello World" ``` @@ -68,10 +68,11 @@ _hello: You may want to build and maintain your own image based on the the image you wanted to use. -```docker +```dockerfile +# Dockerfile FROM node:alpine RUN apk add --update make -... +# ... ``` ::: tip @@ -85,11 +86,12 @@ Mounting volumes with Docker on Mac or Windows can be slow. For instance, develo On Mac, using the `native_osx` strategy can also help. The Docker Compose file would look like the following: ```yaml +# docker-compose.yml yourservice: image: animage volumes: - app-sync:/opt/app:nocopy -... +# ... volumes: # this volume is created by docker-sync. See docker-sync.yml for the config diff --git a/docs/guide/environment-variables.md b/docs/guide/environment-variables.md index a3eb0df..df9a45e 100644 --- a/docs/guide/environment-variables.md +++ b/docs/guide/environment-variables.md @@ -8,7 +8,8 @@ Often there are many environment variables and having them in a `.env` file beco With the following `.env` file: -``` +```bash +# .env # make sure these env vars are not set in the system ENV_A ENV_B= @@ -18,6 +19,7 @@ ENV_C=env_c And the `docker-compose.yml` file: ```yaml +# docker-compose.yml services: alpine: image: alpine @@ -27,14 +29,14 @@ services: The expected results are: ```bash -$ docker run --rm --env-file=.env alpine env -ENV_B= -ENV_C=env_c +docker run --rm --env-file=.env alpine env +#ENV_B= +#ENV_C=env_c # ENV_A is not set and ENV_B is set to empty -$ docker compose run --rm alpine env -ENV_B= -ENV_C=env_c +docker compose run --rm alpine env +#ENV_B= +#ENV_C=env_c # Same as Docker ``` @@ -42,7 +44,8 @@ ENV_C=env_c Environment variables can be used at different stages of software development: build, test, deploy, and run time. The following is an example how to keep .envfile structured. -``` +```bash +# .env # All ENV diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md index f0633d1..5a4e115 100644 --- a/docs/guide/getting-started.md +++ b/docs/guide/getting-started.md @@ -2,7 +2,7 @@ -Let's print out `Hello, World!` in the console using the 3 Musketeers. The command `make echo` will be calling Docker to run the command `echo 'Hello, World!'` inside a container. +Let's print out `Hello, World!` in the terminal using the 3 Musketeers. The command `make echo` will be calling Docker to run the command `echo 'Hello, World!'` inside a container. ![getting-started](./assets/getting-started.mmd.svg) @@ -14,7 +14,7 @@ Let's print out `Hello, World!` in the console using the 3 Musketeers. The comma ## Hello, World! -Create the following two files +Create the following two files: ```yaml # docker-compose.yml @@ -30,10 +30,10 @@ echo: docker compose run --rm alpine echo 'Hello, World!' ``` -Then simply echo "Hello, World!" with the following command: +Then simply run: ```bash -$ make echo +make echo ``` [linkDocker]: https://docs.docker.com/engine/installation/ diff --git a/docs/guide/index.md b/docs/guide/index.md index fd1c41e..66b8295 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -36,7 +36,7 @@ Test your code and pipelines locally before your CI/CD tool runs it. Feel confid Animated demo -_The demo was generated with VHS using the 3 Musketeers ([source](https://github.com/flemay/3musketeers/tree/main/demo))_ +_The demo was generated with VHS using the 3 Musketeers ([source](https://github.com/flemay/3musketeers/tree/main/demo))._ --- diff --git a/docs/guide/make.md b/docs/guide/make.md index 31536ca..00c6b18 100644 --- a/docs/guide/make.md +++ b/docs/guide/make.md @@ -17,13 +17,14 @@ This is mainly when using [Make in a pattern][linkPatternsMake]. Using `target` and `_target` is a naming convention to distinguish targets that can be called on any platform (Windows, Linux, MacOS) versus those that need specific environment/dependencies. ```makefile +# Makefile # buid target uses Compose which is available on Windows, Unix, and MacOS deploy: docker compose run --rm serverless make _deploy # This _deploy target depends on a NodeJS environment and Serverless Framework which may not be available on the hosts. # It is executed in a Docker container that provides the right environment for its execution. -# If the host has NodeJS and Serverless Framework installed, `$ make _build` can be called. +# If the host has NodeJS and Serverless Framework installed, `make _build` can be called. _deploy: serverless deploy ``` @@ -35,6 +36,7 @@ _deploy: By default `.PHONY` can be left out unless the target collides with the name of file/folder. One case is a target `test` which often conflicts with a folder named `test`. ```makefile +# Makefile # can be written into a single line with other targets that need .PHONY .PHONY: test targetA targetB @@ -53,6 +55,7 @@ Sometimes you want the target to match the name of a file in which case `.PHONY` Docker and Compose commands can be assigned to variables. ```makefile +# Makefile COMPOSE_RUN_NODE = docker compose run --rm serverless deploy: @@ -62,6 +65,7 @@ deploy: Or ```makefile +# Makefile NODE_RUN = docker compose run --rm serverless deploy: @@ -77,6 +81,7 @@ Use [Pipeline targets][linkPipelineTargets] as a way to describe the list of dep ::: ```makefile +# Makefile deploy: package.zip $(COMPOSE_RUN_NODE) make _deploy ``` @@ -90,6 +95,7 @@ We call Pipeline targets the targets that have a```list of dependencies, usually It is best having them at the top of the Makefile as they give an understanding of the application pipelines when reading the Makefile. ```makefile +# Makefile # pipeline targets first stageTest: build test clean @@ -98,9 +104,10 @@ stageTest: build test clean ## make and target all -Running only `$ make` will trigger the first target from the Makefile. A convention among developer is to have a target `all` as the first target. In the 3 Musketeers context, `all` is a perfect [pipeline target][linkPipelineTargets] to document and test locally the sequence of targets to test, build, run, etc. +Running only `make` will trigger the first target from the Makefile. A convention among developer is to have a target `all` as the first target. In the 3 Musketeers context, `all` is a perfect [pipeline target][linkPipelineTargets] to document and test locally the sequence of targets to test, build, run, etc. ```makefile +# Makefile # first target all: deps test build clean @@ -108,7 +115,10 @@ all: deps test build clean ``` ```sh -$ make # will run the target all +# Run target `all` +make all +# Or +make ``` ## Ordering targets @@ -120,6 +130,7 @@ Ordering targets in some ways may help maintaining the Makefile in the long run. - Ordering targets in a build pipeline flow ```makefile + # Makefile deps: # ... test: @@ -133,6 +144,7 @@ Ordering targets in some ways may help maintaining the Makefile in the long run. - Group [target and _target][linkTargetVSUnderscoreTarget] together ```makefile + # Makefile deps: # ... _deps: @@ -146,6 +158,7 @@ Ordering targets in some ways may help maintaining the Makefile in the long run. - Alternatively, [target and _target][linkTargetVSUnderscoreTarget] can be separated if too verbose. ```makefile + # Makefile deps: # ... test: @@ -183,6 +196,7 @@ It is a good thing to have a target `deps` for installing all the dependencies r A tar file of the dependencies can be created as an artifact to be passed along through the CI/CD stages. This step is useful as it acts as a cache. Subsequent CI/CD stages will have the exact same dependencies. Moreover, it is faster to pass along a tar file than a folder with many files. ```makefile +# Makefile COMPOSE_RUN_NODE = docker compose run --rm node DEPS_DIRS = node_modules DEPS_ARTIFACT = $(DEPS_DIRS).tar.gz @@ -217,13 +231,13 @@ DEPS_DIRS = node_modules vendor packages/**/dist/* ## Calling multiple targets in a single command -Make allows you to call multiple targets in a single command like this `$ make targetA targetB targetC`. This is useful if you want to use a different `.env` file and call another target +Make allows you to call multiple targets in a single command like this `make targetA targetB targetC`. This is useful if you want to use a different `.env` file and call another target ```bash # create .env with the default -$ make envfile anotherTarget +make envfile anotherTarget # create .env from another file -$ make envfile anotherTarget ENVFILE=your.envfile +make envfile anotherTarget ENVFILE=your.envfile ``` ## Prevent echoing the command @@ -231,6 +245,7 @@ $ make envfile anotherTarget ENVFILE=your.envfile The symbol `@` prevents the command to be printed out prior its execution. Useful when there are secrets at stake. ```makefile +# Makefile # If '@ 'is omitted, `DOCKER_PASSWORD` would be revealed. push: @echo "$(DOCKER_PASSWORD)" | docker login --username "$(DOCKER_USERNAME)" --password-stdin docker.io @@ -243,6 +258,7 @@ push: The symbol `-` allows the execution to continue even if the command failed. ```makefile +# Makefile TAG=v1.0.0 # _tag creates a new tag and fails if the tag already exists @@ -260,7 +276,7 @@ _overwriteTag: ## Clean Docker and files -Using Compose creates a network that you may want to remove after your stage or pipeline is completed. You may also want to remove existing stopped and running containers. Moreover, files and folders that have been created can also be cleaned up after. A pipeline would maybe contain a stage clean or call clean after `test` for instance: `$ make test clean`. +Using Compose creates a network that you may want to remove after your stage or pipeline is completed. You may also want to remove existing stopped and running containers. Moreover, files and folders that have been created can also be cleaned up after. A pipeline would maybe contain a stage clean or call clean after `test` for instance: `make test clean`. `clean` could also have the command to clean Docker. However having the target `cleanDocker` may be very useful for targets that want to only clean the containers. See section [Managing containers in target][linkManagingContainersInTarget]. @@ -274,6 +290,7 @@ rm: cannot remove ‘vendor/gopkg.in/yaml.v2/README.md’: Permission denied This happens because the creation of those files was done with a different user (in a container as root) and the current user does not have permission to delete them. One way to mitigate this is to call the command in the docker container. ```makefile +# Makefile cleanDocker: docker compose down --remove-orphans @@ -292,6 +309,7 @@ Sometimes a target needs to run a container in order to execute its task. For instance, a target `test` may need a database to run prior executing the tests. ```makefile +# Makefile # target test calls cleanDocker before starting a postgres container test: cleanDocker startPostgres $(DOCKER_RUN_NODE) make _test @@ -312,6 +330,7 @@ cleanDocker: The Makefile can be split into smaller files. ```makefile +# Makefile # makefiles/deploy.mk deploy: docker compose run --rm serverless make _deploy @@ -322,6 +341,7 @@ _deploy: ```makefile # Makefile +# Makefile include makefiles/*.mk ``` @@ -334,6 +354,7 @@ In some situations, targets become very complex due to the syntax and limitation [This][linkSelfDocumentedMakefileGist] is pretty neat for self-documenting the Makefile. ```makefile +# Makefile # Add the following 'help' target to your Makefile # And add help text after each target name starting with '\#\#' DOCKER_RUN_MUSKETEERS = docker run --rm -v $(PWD):/opt/app -w /opt/app flemay/musketeers diff --git a/docs/guide/patterns.md b/docs/guide/patterns.md index 5c5879b..52870d2 100644 --- a/docs/guide/patterns.md +++ b/docs/guide/patterns.md @@ -9,10 +9,11 @@ In a nutshell, Make calls either Docker or Compose which then runs a Command ins ![pattern-overview](./assets/pattern.mmd.svg) ::: tip -The [3 Musketeers repository][link3MusketeersGitHub] does implement the patterns +The [3 Musketeers repository][link3MusketeersGitHub] applies the patterns: -- Compose: Most of the [Makefile](https://github.com/flemay/3musketeers/blob/main/Makefile) targets -- Docker-in-Docker: [Generate the demo with VHS](https://github.com/flemay/3musketeers/tree/main/demo) +- Compose: [this website development](https://github.com/flemay/3musketeers?tab=readme-ov-file#3-musketeers-website-development) +- Docker: section [Getting started](https://github.com/flemay/3musketeers?tab=readme-ov-file#getting-started) +- Docker-in-Docker: [demo generated with VHS](https://github.com/flemay/3musketeers/tree/main/demo) ::: ## Compose @@ -54,7 +55,7 @@ _echo: ``` ```bash -$ make echo +make echo ``` #### Shell @@ -76,7 +77,7 @@ echo: ``` ```bash -$ make echo +make echo ``` #### Shell file @@ -91,7 +92,7 @@ echo Hello, World! ```bash # set executable permission -$ chmod +x echo.sh +chmod +x echo.sh ``` ```yaml @@ -112,7 +113,7 @@ echo: ``` ```bash -$ make echo +make echo ``` #### Go @@ -148,7 +149,7 @@ echo: ``` ```bash -$ make echo +make echo ``` #### npm @@ -184,7 +185,7 @@ echo: ``` ```bash -$ make echo +make echo ``` ## Docker @@ -194,12 +195,13 @@ Make calls directly Docker instead of Compose. Everything that is done with Comp ![pattern-docker](./assets/pattern-docker.mmd.svg) ```makefile +# Makefile echo: docker run --rm alpine echo 'Hello, World!' ``` ```bash -$ make echo +make echo ``` ## Docker-in-Docker (DinD) diff --git a/docs/guide/project-dependencies.md b/docs/guide/project-dependencies.md index 527eeea..43c5622 100644 --- a/docs/guide/project-dependencies.md +++ b/docs/guide/project-dependencies.md @@ -37,7 +37,8 @@ services: If a project has specific dependency requirements, then creating (and maintaining) custom Docker images may be overkill. Instead, the project could have a Dockerfile that encapsulates the dependencies. This approach requires the image to be built locally before use. -```docker +```dockerfile +# Dockerfile FROM alpine:latest RUN apk --update add bash curl nodejs npm git \ && rm -rf /var/cache/apk/*