In this part we will setup a local instance of Bitbucket server using an evaluation license so we can push and pull code locally to test drive our build pipeline. It is fairly likely that you already use Bitbucket or Github or something like that to manage your Git repositories - the idea is the same as what we will be doing here so these instructions can be applied to whatever you are using though you’ll need to read the docs for your platform.
I picked Bitbucket server because I can run it easily on my localhost and it is just for experimentation purposes so I don’t mind deleting it when I’m done.
We will use Docker to assist us with running Bitbucket which makes for a surprisingly easy setup. Start off by pulling down the Bitbucket Docker image we want to use:
docker pull atlassian/bitbucket-server:6.10
This will fetch the Bitbucket server Docker image to our local machine, ready for us to use it. I am opting for version
Important: I am using version
6.10deliberately as there is (at the time of writing) an outstanding bug in the Jenkins plugin we will need to use for webhooks that breaks pull request builds from Bitbucket 7+. I think there is a fix on the way so this might not be required at a later date.
When it’s done you can view the current Docker images to confirm it was downloaded:
$ docker images REPOSITORY TAG IMAGE ID SIZE iac-env latest 1541cb836ece 714MB atlassian/bitbucket-server 6.10 09c4f264b197 945MB ubuntu bionic c3c304cb4f22 64.2MB
We will run Bitbucket as a Docker container - create a shell script named
start-bitbucket.sh and give it executable permissions:
#!/usr/bin/env bash # After Bitbucket has started it can be browsed at http://localhost:7990 # To access the Bitbucket data folder you can mount the Docker volume # assigned to Bitbucket with the volume name: 'bitbucket-data', typically # found at: /var/lib/docker/volumes/bitbucket-data on Linux. If you are # running Docker on MacOS, the volumes are hidden inside a Docker VM. # # Bitbucket will auto restart after a system shutdown/reboot unless it was # manually stopped, so theoretically you should only need to ever start it # once. If for some reason you do want to manually stop Bitbucket, use the # following command: # # docker stop bitbucket # echo 'Starting Bitbucket ...' docker run \ -d \ --name bitbucket \ --network iac-env \ --publish 7990:7990 \ --publish 7999:7999 \ --restart unless-stopped \ --volume bitbucket-data:/var/atlassian/application-data/bitbucket \ atlassian/bitbucket-server:6.10
We are specifying the
-d argument to have the Bitbucket image run in the background. We also want Bitbucket to automatically restart itself when the host machine is rebooted - if you don’t want that behaviour just remove the
--restart unless-stopped argument.
We are publishing ports
7999 as they are the ports Bitbucket will be running on so it needs to be bound to expose it to the external environment. Note we are also using
--network iac-env in a similar way to our
iac-env image - this is to allow Bitbucket to call other network resources on the host machine within the
iac-env Docker network - such as Jenkins a bit later on.
--volume argument is critical - we are mapping a location on our local file system as the place for Bitbucket to store all its data and state. If we didn’t do this, all of our Bitbucket repositories and configuration would be lost when the Docker container is terminated! As per the comments in the script, the actual files will be stored in
/var/lib/docker/volumes/bitbucket-data if you are running Docker on Linux. If you are running Docker on MacOS, volumes are actually stored inside a Docker virtual machine - you’ll need to read the docs to find out how to access them.
Run the shell script to boot up Bitbucket for the first time, then browse to http://localhost:7990 to access it - you might have to wait a couple of minutes for it to boot up.
Note: We reach Bitbucket (and Jenkins later) via
localhostonly when browsing from the host machine that is running Docker. Networking done within the Bitbucket/Jenkins containers must use the
iac-envnetwork bridge instead.
When Bitbucket has started, choose
Internal - For evaluation and demo purposes only. and continue. For the next part you will need an Atlassian account (it’s free) to provision an evaluation license. This is a bit annoying but for the sake of this experiment it’s not that bad. Once you’ve navigated through the license activation and created your first admin user you will be greeted with the welcome screen:
We will create ourselves a new Bitbucket project so we have a place to push and pull code from. Create a new project with the following configuration:
After creating the project, add a new repository to it for our example project:
Ok cool, we have a new repository in Bitbucket with nothing in it. Let’s create our first Git branch.
Create a folder next to our
setup folder named
example-project with a simple text file in it named
readme.md - put whatever you like in it:
. ├─+ example-project │ └── readme.md ├─+ setup └── start-bitbucket.sh
Navigate into the
example-project and create and push our first Git commit for it:
git init git add --all git commit -m "Initial Commit" git remote add origin http://localhost:7990/scm/ic/example-project.git git push -u origin master
Check Bitbucket to see that you now have a new branch named
master with your
readme.md file in it:
We will add a new user to Bitbucket to allow Jenkins to talk to it. Without doing this there won’t be a way for Jenkins to check out code to perform builds, or notify Bitbucket when builds have succeeded or failed.
In Bitbucket, select the small cog icon near the top right of the screen to enter the
Administration area, then select
Create user. Fill in the details like below to create a
jenkins user. Be sure to remember whatever password you specify as we’ll need to enter it into Jenkins later:
Now navigate to
Infrastructure as Code ->
Project Settings ->
User access section, add the new
jenkins user with
jenkins user can now authenticate to Bitbucket to allow it to check code within its build pipelines.
We can now apply some final configuration settings to our
example-project repository to make it ready for a pull request based workflow with integration with Jenkins.
We want to prevent anyone from pushing code directly into our master branch - instead we want them to raise a pull request before code can be merged. We will set up branch permissions to help us with this. Navigate to the settings for the
example-project then into
Branch permissions under the
Add permissions, then match the options to the settings below - this will prevent any direct pushes to the
Now we need to configure our repository such that any Git changes we care about will trigger notifications to Jenkins. This part is pretty cool because it will be the first example of using the names of our Docker containers to connect them to each other through our custom
We will be using the
Post Webhooks third party plugin for firing our webhooks: https://marketplace.atlassian.com/apps/1215474/post-webhooks-for-bitbucket?hosting=server&tab=overview.
Go to the global Bitbucket settings - it’s the small cog icon in the top right - and navigate to
Find new apps in the
ADD-ONS section. Search for
Post Webhooks for Bitbucket and install it.
While we are here, we need to change the base url of our Bitbucket server otherwise the webhooks plugin won’t work. Select
Server settings under the
SETTINGS section and change the
Base URL field to
Now navigate into our
example-project repository and into its settings then select
Important: Go to
Add Webhook and enter the details like below:
http://jenkins:8080 as the destination to send triggers to - which in our case will be Jenkins. Although we haven’t created our Jenkins Docker image yet, we will run it with the name
jenkins which is how our network bridge will associate it to
Note: The webhook won’t be able to connect to Jenkins yet as we aren’t running it yet!
That’s about it for Bitbucket, next up we will run Jenkins and have it talk to Bitbucket to run a build pipeline every time code is changed.
Source code can be found at: https://github.com/MarcelBraghetto/iac-env
End of part 3