A microservice backend written in Go for a social media app.
- Signup and login
- Post creation, comment/like functionality and statistics
- Presigned links for the frontend to upload post images
- Following functionality and paginated feed
Whether you want to run the project locally or remotely, first clone the repository:
git clone https://github.com/avoronoi/smappThen, generate the Go code for the gRPC client and server from the .proto files. Ensure that you have Go and the Protocol Buffer compiler (protoc) installed. Additionally, install the following packages:
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latestThen execute:
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative common/grpc/user/user.proto
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative common/grpc/image/image.proto You will also need to install gomplate, a template renderer that will be used to generate the docker-compose.yml file.
There are two options to run the app: using Docker Compose and Docker Swarm.
Docker Compose runs only on a single node, so it should only be used for development. It builds images from the services' Dockerfiles and supports rebuilding services on code changes using docker compose watch. The configurations for docker compose watch are specified in the docker-compose.override.yml file.
To run the application, first generate the docker-compose.yml file:
LOCAL=1 gomplate -f docker-compose.yml.tmpl -o docker-compose.ymlNext, create a MySQL root password and store it in the secrets/mysql_password.txt file. Then, create an RSA key pair and store it in the secrets/jwt_private_key.pem and ./jwt_public_key.pem files.
You can customize these locations in the docker-compose.override.yml file.
Docker Swarm does not build images from Dockerfiles and requires prebuilt images to be stored in a registry.
You can use a container registry like Amazon ECR to store them. If you want to run Docker Swarm locally, you can create a container from Docker's registry:2 image:
docker run -d -p 5000:5000 --name registry registry:2And then use localhost:5000 as registry.
Generate the docker-compose.yml file:
DEPLOY=1 gomplate -f docker-compose.yml.tmpl -o docker-compose.ymlYou should also specify LOCAL=1 if you intend to run Swarm locally.
Next, build and push images to the registry:
docker compose build --pushFirst, initialize the Swarm on one of the nodes with ./deployment/init_swarm.sh.
This command initializes the Swarm (making the current node its only member) and sets up Swarm secrets and configs.
Run docker swarm join-token manager or docker swarm join-token worker to get a command for joining the Swarm as a manager or worker, respectively. Execute the generated command on the nodes you want to add.
Some nodes act as gateways. When running on an EC2 cluster, these nodes should be the ones that the Application Load Balancer forwards requests to. To designate a node as a gateway, execute ./deployment/set_gateway.sh on it.
Finally, deploy the application from one of the manager nodes:
./deployment/deploy.sh <REGISTRY_ENDPOINT>To apply database migrations, use the Flyway migration tool from within the appropriate container.
From the user-db-migrations container:
flyway -url=jdbc:mysql://user-db:3306/user-db?allowPublicKeyRetrieval=true -user=root -password=$(cat /run/secrets/mysql_password) migrateFrom the post-db-migrations container:
flyway -url=jdbc:mysql://post-db:3306/post-db?allowPublicKeyRetrieval=true -user=root -password=$(cat /run/secrets/mysql_password) migrateEnsure that you have AWS credentials configured with necessary permissions. Then run:
cd terraform
terraform init
terraform applyEnter the variable values when prompted. You can also specify them in a terraform/variables.tfvars file (see terraform/variables.tfvars.example).
To install the necessary packages, create a Swarm and mark necessary nodes as gateways, run:
terraform output -json | (cd ../deployment; go run ./cmd/install_all/main.go)Then run ./deployment/scripts/deploy.sh <REGISTRY URL> from one of the nodes.